API reference

Other Node core modules

16/17Coverage3/17Strict (zero caveats)

The smaller Node built-ins, grouped here rather than each given a full page. net, tls, http and https are Node's own layering ported to TypeScript — a net.Socket is a Duplex over a native TCP handle, a TLSSocket a Socket whose handle carries a non-blocking OpenSSL session, and http/https build on them — all on one event loop with dgram and dns. Messages across process and channel boundaries (cluster, diagnostics_channel) are strings, and vm stays out of scope behind the same blocker as bare eval().

Exact Works, with caveats Not supported

querystring (.parse, .stringify, .escape, .unescape)

Exact
querystring.parse(str: string, sep?: string, eq?: string, options?: ParseOptions): ParsedUrlQuery; querystring.stringify(obj?: ParsedUrlQueryInput, sep?: string, eq?: string, options?: StringifyOptions): string

Node's legacy "a=b&c=d" parse/stringify, ported from Node's own lib/querystring.js. parse returns a null-prototype object; a repeated key collects its values into an array; a leading '?' is plain text (unlike new URLSearchParams(str)). stringify takes an object whose array values repeat the key. Custom separators, maxKeys and custom encode/decode functions are honoured; escape, unescape, unescapeBuffer, encode and decode are exported too.

Parameters
str / objstring | ParsedUrlQueryInput
A raw query tail to parse, or an object to serialize.
sep, eqstring
The pair and key/value separators ('&' and '=' by default).
Returns

ParsedUrlQuery | string — The parsed object, or the serialized query string.

const parsed = querystring.parse("topic=compilers%20and%20types&tag=a&tag=b")
console.log(parsed.topic)  // compilers and types
console.log(parsed.tag)    // [ 'a', 'b' ]
See it in a full example →

assert (.ok, bare assert(cond, msg?), .equal/.strictEqual, .notEqual/.notStrictEqual, .deepEqual/.deepStrictEqual (+not*), .fail, .throws, .match/.doesNotMatch)

Works, with caveats
assert(value: unknown, message?: string | Error): asserts value; assert.strictEqual(a, b); assert.deepStrictEqual(a, b); assert.throws(fn, error?); await assert.rejects(promise)

Node's assertion library, ported from Node's own sources: the same checks, the same AssertionError (name, code, actual, expected, operator), and the same failure messages and diffs, including assert.ok quoting the failing call's source. Distinct from console.assert, which logs and continues.

Returns

void — Nothing, or throws AssertionError.

assert.strictEqual("a" + "b", "ab")
assert.throws(() => { throw new Error("boom") })
See it in a full example →
⚠ Differences from standard
  • No assert.CallTracker (deprecated in Node)
  • Deep equality does not compare symbol-keyed properties, and a failure diff does not invoke getters
  • An uncaught AssertionError prints Uncaught: <message> rather than Node's name, stack and property block

test / node:test

Works, with caveats
import test, { describe, it } from 'node:test'; test(name, options?, fn); import { mustCall } from 'test'

Node's test runner: tests run after the module, one at a time in registration order, with describe/it suites, skip/todo, the TestContext (t.test, t.skip, t.todo, t.diagnostic, t.plan) and before/after/beforeEach/afterEach hooks, reported in Node's spec format with its summary and a nonzero exit on failure. The bare 'test' specifier is Node's own test-suite helpers: mustCall/mustCallAtLeast (counts checked at exit), mustSucceed, mustNotCall, expectsError, expectWarning, skip, and the platform probes.

Returns

Promise<void> | T — Registration, or a counting wrapper of the callback.

⚠ Differences from standard
  • A failing test's details omit Node's test at <file>:<line>:<col> line and the stack: the error prints as Name [code]: message.
  • No mock.*, run(), snapshots, concurrency, timeouts, t.signal/t.assert, or only filtering.
  • The spec reporter prints without colors on a terminal (Node colors it); no other reporter.

util (.inspect, .format)

Works, with caveats
util.format(fmt?: any, ...args): string; util.inspect(value, options?): string; util.isDeepStrictEqual(a, b): boolean; util.promisify(fn); util.callbackify(fn)

Node's util, ported from Node's own lib/util.js: format and formatWithOptions walk the specifiers at run time as Node does (%s calls a program's own toString), inspect takes depth, compact, sorted, breakLength and maxArrayLength, and callbackify, deprecate, debuglog, styleText, types and the system-error lookups behave as Node's.

Parameters
fmtstring
A format string for .format (any string, at run time).
valueany
The value to render for .inspect.
Returns

string — The formatted/inspected string.

console.log(util.format("%s = %d", "count", 42))
console.log(util.inspect({ name: "kml", tags: ["ts", "native"] }))
See it in a full example →
⚠ Differences from standard
  • .promisify wraps a function value and honours promisify.custom; a code-generated builtin (fs.readFile) is not a function value to pass it
  • promisify(f) === f is false for an already-promisified f
  • .inspect ignores colors, showHidden, getters, maxStringLength and numericSeparator; compact: true is treated as 3; a custom method's depth argument is Infinity, not null, when the depth is unlimited
  • No inherits, MIMEType or getCallSites

net (TCP server: net.createServer, server.listen/address()/on('connection'|'listening')/close; TCP client: net.connect/createConnection (positional or { port, host }); connection socket .on('data'|'end')/.write/.end/.address()/.destroy()/.setNoDelay()/.setKeepAlive(); net.isIP/isIPv4/isIPv6)

Works, with caveats
net.createServer(cb).listen(port, cb?); net.connect(port, host?, cb?)

Node's lib/net.js ported to TypeScript over native TCP handles on the event loop. A Socket is a Duplex — back-pressure and 'drain', pause/resume, setEncoding, setTimeout, ref/unref; Server listens by port/host/backlog/options or a Unix-socket path, dual-stack :: by default. Errors are built as Node builds them (connect ECONNREFUSED, getaddrinfo ENOTFOUND, with .code/.errno/.syscall/.address/.port).

Returns

net.Server | net.Socket — A server or connection handle.

const server = net.createServer((socket) => {
  socket.on('data', (chunk: Uint8Array) => { socket.write(chunk); });
});
server.listen(9099);
See it in a full example →
⚠ Differences from standard
  • connect/createConnection take a port, an options object or { path }; the connect is non-blocking and a failure arrives as an async 'error' then 'close'
  • listen's 'listening' and 'error' fire on the next tick, as in Node; maxConnections and getConnections are supported; isIP/isIPv4/isIPv6
  • BlockList, SocketAddress and happy-eyeballs address selection (autoSelectFamily) are not ported

dgram (UDP sockets: createSocket('udp4'), bind, address(), setBroadcast(), on('message'), send, close)

Works, with caveats
dgram.createSocket('udp4' | 'udp6' | options, listener?); socket.bind(port?, address?, cb?); socket.send(msg, port, address, cb?)

Node's UDP sockets: udp4/udp6, bind with 'listening', send in every form (offset/length, lists, before the bind completes), connect/disconnect, the broadcast/TTL/multicast options and group membership, buffer sizes, ref/unref. 'message' receives a Buffer and { address, family, port, size }.

Returns

dgram.Socket — A UDP socket handle.

const server = dgram.createSocket('udp4');
server.on('message', (msg, rinfo) => {
  server.send('reply:' + msg.toString(), rinfo.port, rinfo.address);
});
server.bind(0, '127.0.0.1');
See it in a full example →
⚠ Differences from standard
  • Sends are synchronous, so getSendQueueSize()/getSendQueueCount() are always 0.
  • The lookup and block-list options, bind({ fd }) and cluster-shared sockets are not ported.

tls (TLS-wrapped sockets)

Works, with caveats
tls.connect(port, host[, {rejectUnauthorized}][, onSecureConnect]); tls.createServer({ cert, key }, connectionListener)

Node's _tls_wrap shape in TypeScript: a TLSSocket is a net.Socket whose handle carries a non-blocking OpenSSL session, so the handshake runs on the event loop. tls.connect supports servername, rejectUnauthorized, ca/cert/key and ALPN, firing 'secureConnect' with authorized/authorizationError and Node's verify error codes and messages; tls.createServer emits 'secureConnection' and 'tlsClientError'; createSecureContext, getProtocol and getCipher.

Returns

tls.TLSSocket | tls.Server — A net-shaped TLS handle.

const sock = tls.connect(443, "example.com", () => {
  sock.write("GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n");
});
sock.on("data", (chunk: string) => { response += chunk; });
See it in a full example →
⚠ Differences from standard
  • OpenSSL-only (libssl) — a -crypto=commoncrypto build using tls is a clean compile error (Mac's CommonCrypto has no TLS API)
  • Session resumption, OCSP, renegotiation, PSK and getPeerCertificate()'s certificate object are not ported

dns (dns.lookup, dns.resolve4/resolve, dns.promises.lookup)

Works, with caveats
dns.lookup(host, [options,] cb); dns.resolve4(host, [{ ttl }], cb); dns.resolveMx(host, cb); new dns.Resolver(options); await dns.promises.lookup(host)

Node's own lib/dns.js. lookup and lookupService run getaddrinfo/getnameinfo on the thread pool, as libuv does (all, family, hints, order); the resolve family — resolve4/6 with TTLs, MX, TXT, SRV, NS, CNAME, PTR, SOA, NAPTR, CAA, TLSA, ANY, reverse — is Node's cares_wrap over c-ares: the system's servers, Resolver timeouts, tries, setServers, cancel and setLocalAddress, cares_wrap's record shapes, and Node's error codes (ENOTFOUND, ENODATA, ETIMEOUT, …). dns.promises and dns/promises are the promise forms.

Parameters
hoststring
The hostname to resolve.
Returns

object | Promise<…> — The request (callbacks arrive on a later tick), or a Promise.

dns.lookup("localhost", (err, address, family) => {
  console.log("localhost ->", address, "family", family);
});
See it in a full example →
⚠ Differences from standard
  • A resolve error has no errno key (Node's has errno: undefined)

zlib (gzip/gunzip, deflate/inflate, deflateRaw/inflateRaw, unzip, each *Sync + (err, result) callback)

Works, with caveats
zlib.gzipSync(input, options?): Buffer; zlib.gzip(input, options?, (err, out) => …); zlib.createGzip(options?): Gzip; zlib.crc32(data, value?): number

Node's zlib module: the Deflate/Inflate/Gzip/Gunzip/DeflateRaw/InflateRaw/Unzip streams and their create* functions, the one-shot methods (callback and *Sync), crc32, constants and codes, with every zlib option. Each stream owns a native zlib handle whose writes run on the thread pool. Input may be a Buffer/TypedArray, ArrayBuffer, DataView, or string (UTF-8); output is always a Buffer.

Parameters
inputstring | Buffer | TypedArray | DataView | ArrayBuffer
The data to compress or decompress.
optionsZlibOptions
flush, finishFlush, chunkSize, windowBits, level, memLevel, strategy, dictionary, info, maxOutputLength, rejectGarbageAfterEnd.
Returns

Buffer — The compressed/decompressed bytes (a stream for create*).

const gz = zlib.gzipSync(text)
console.log("gunzip:", dec.decode(zlib.gunzipSync(gz)) === text)
pipeline(Readable.from(parts), zlib.createGzip({ level: 6 }), zlib.createGunzip(), sink, done)
See it in a full example →
⚠ Differences from standard
  • Brotli and Zstd load the system libbrotli/libzstd at run time (Node bundles them); where they are missing, a Brotli or Zstd stream is ERR_ZLIB_INITIALIZATION_FAILED
  • Compressed bytes are the system libz's, which can differ from Node's bundled zlib at the same level (each inflates the other's)
  • A *Sync call with info: true is typed { buffer, engine } (@types types it Buffer)

vm (vm.Script, sandboxed eval-like execution)

Not supported
// not supported

Not implemented. vm hits the same fundamental blocker as bare eval() — there is no embedded engine to run source assembled at runtime. An opt-in embedded-engine path is scoped but not started.

diagnostics_channel (channel/subscribe/unsubscribe/hasSubscribers/tracingChannel, Channel, TracingChannel)

full
const ch = diagnostics_channel.channel(name); ch.subscribe(fn); ch.publish(message)

Node's module: named channels whose subscribers receive any published value and the channel name; bound stores and runStores; tracing channels that publish start/end/asyncStart/asyncEnd/error around traceSync, tracePromise and traceCallback. A subscriber's throw is reported on the next tick without stopping the others.

Returns

Channel | TracingChannel | boolean | void — A channel, a tracing channel, a subscription result, or nothing.

http client (http.get/http.request)

Works, with caveats
http.get(url, res => …); const req = http.request(opts); req.write(body); req.end()

Node's _http_agent/_http_client in TypeScript over net. http.get and http.request return a ClientRequest (an OutgoingMessage) and the response is an IncomingMessage — a Readable.

Returns

ClientRequest — A request handle; the response arrives via callback.

⚠ Differences from standard
  • ClientRequest: chunked or Content-Length bodies, 'response'/'socket'/'information'/'upgrade'/'error', abort/destroy/setTimeout
  • http.Agent pools keep-alive sockets; http.globalAgent keeps them alive and unref'd, as Node 19+
  • http.request(new URL(…)) is not accepted — pass a string or an options object

https (client: https.get/https.request)

Works, with caveats
https.get(url, res => …); const req = https.request(opts); req.end()

https.createServer is a tls.Server running the http module's connection handling; https.request/get/Agent/globalAgent connect with tls.connect. Same request and response objects as http.

Returns

ClientRequest — A request handle; the response arrives via callback.

⚠ Differences from standard
  • Same client limit as http for a URL argument

stream/web (re-exports: ReadableStream/WritableStream/TransformStream/CompressionStream/DecompressionStream)

Exact
import { ReadableStream, TransformStream } from 'stream/web'

The names bind as identity to the ambient WHATWG constructors that already exist — importing them from stream/web is interchangeable with using the globals. The queuing-strategy classes are not exported.

Returns

typeof ReadableStream — The same ambient constructors as the globals.

cluster (fork, worker messaging, isPrimary/isWorker/worker, Worker.id/.process)

Works, with caveats
cluster.fork(env?); cluster.on('listening', (worker, address) => {}); cluster.workers[id]; cluster.setupPrimary(settings); cluster.disconnect(cb?)

Node's cluster module. The primary forks workers that run this same program; a worker's net or http server listens through the primary, which either accepts connections and hands them to the workers in turn (round-robin, the default outside Windows) or gives every worker the listening socket itself. Workers and the primary exchange messages, handles included, over the fork channel.

Returns

cluster.Worker — A worker handle.

⚠ Differences from standard
  • setupPrimary({ exec }) naming another file fails at fork(): a worker is this compiled program, so there is no other script for it to run
  • inspectPort and the inspector flags are ignored: a compiled program has no inspector
  • A dgram socket bound in a worker binds on its own, not through the primary
  • Windows: a worker's listen does not work yet — descriptor passing over the fork channel is POSIX-only

http2 **module** (http2.createServer/connect, Http2Session/Http2Stream)

Works, with caveats
http2.createServer((req, res) => …) | .on('stream', (stream, headers) => …); http2.connect(url).request(headers)

Node's http2 module: HTTP/2 servers (cleartext h2c and TLS with ALPN, optionally answering HTTP/1.1) and client sessions, with the compat request/response API, the core stream API, push streams, settings, ping and goaway.

Returns

Http2Session | Http2Stream — A session or stream handle.

const server = http2.createServer();
server.on('stream', (stream, headers) => {
  stream.respond({ ':status': 200, 'content-type': 'text/plain' });
  stream.end("hello " + headers[':path'].slice(1));
});
See it in a full example →
⚠ Differences from standard
  • respondWithFD/respondWithFile read the whole file into memory before sending it, where Node streams it
  • session.altsvc()/origin() validate their arguments but send no frame; setNextStreamID/setLocalWindowSize validate only
  • session.socket is the raw socket, not Node's Proxy guarding the session-owned socket methods
  • The Http2ServerRequest/Http2ServerResponse subclass options are ignored
  • stream.write has no backpressure: it always returns true and buffers
  • Most session tuning options (maxSessionMemory, paddingStrategy, …) are accepted and ignored

async_hooks (AsyncLocalStorage, AsyncResource)

Works, with caveats
const als = new AsyncLocalStorage<T>(); als.run(store, () => als.getStore()); AsyncLocalStorage.snapshot(); new AsyncResource(type).runInAsyncScope(fn)

AsyncLocalStorage carries a store through an async call tree: run/exit/enterWith/getStore/disable and the name/defaultValue options, with the context frame propagating across await (a spawned task inherits it) and into promise reactions and timer, setImmediate, nextTick and queueMicrotask callbacks scheduled inside run(). Static bind/snapshot and AsyncResource (runInAsyncScope, bind) capture the current context and replay it later.

⚠ Differences from standard
  • createHook, executionAsyncId, triggerAsyncId and executionAsyncResource are not exported; asyncId() numbers resources in creation order with no lifecycle events behind it.