Skip to main content
Bun implements Web-standard APIs wherever possible instead of inventing new ones. This means code written for the browser (or other modern runtimes like Deno and Cloudflare Workers) often runs in Bun without changes. Browser-only APIs like the DOM or History API have no meaning in a server context and are not included. Everything else that makes sense server-side is implemented.

HTTP

fetch, Request, Response, and Headers are all globally available. No import is needed.
// fetch is available globally
const response = await fetch("https://example.com/api/data");
const data = await response.json();

// Construct requests and responses manually
const req = new Request("https://example.com", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ hello: "world" }),
});

const res = new Response(JSON.stringify({ ok: true }), {
  status: 200,
  headers: { "Content-Type": "application/json" },
});

AbortController

Use AbortController to cancel in-flight fetch requests.
const controller = new AbortController();
const { signal } = controller;

setTimeout(() => controller.abort(), 5000);

const response = await fetch("https://example.com", { signal });

URLs

URL and URLSearchParams are globally available and work identically to their browser counterparts.
const url = new URL("https://example.com/path?foo=bar&baz=qux");
console.log(url.hostname);       // "example.com"
console.log(url.pathname);       // "/path"
console.log(url.searchParams.get("foo")); // "bar"

const params = new URLSearchParams({ page: "2", limit: "50" });
console.log(params.toString()); // "page=2&limit=50"

Streams

Bun fully implements the WHATWG Streams API.

ReadableStream

A stream of data you can read from, chunk by chunk.

WritableStream

A stream of data you can write to.

TransformStream

A writable stream that produces a readable stream after transformation.

Queuing strategies

ByteLengthQueuingStrategy and CountQueuingStrategy for backpressure control.
// Create a ReadableStream from scratch
const stream = new ReadableStream({
  start(controller) {
    controller.enqueue("hello ");
    controller.enqueue("world");
    controller.close();
  },
});

// Pipe through a TransformStream
const upperCaseStream = new TransformStream({
  transform(chunk, controller) {
    controller.enqueue(chunk.toUpperCase());
  },
});

const reader = stream.pipeThrough(upperCaseStream).getReader();
while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  console.log(value); // "HELLO ", then "WORLD"
}

Blob and File

Blob represents raw binary data. File extends Blob with a name and lastModified.
const blob = new Blob(["hello world"], { type: "text/plain" });
console.log(blob.size);         // 11
console.log(blob.type);         // "text/plain"
const text = await blob.text(); // "hello world"

const file = new File(["file contents"], "hello.txt", { type: "text/plain" });
console.log(file.name);         // "hello.txt"

FormData

FormData is fully implemented, including file uploads.
const form = new FormData();
form.append("username", "alice");
form.append("avatar", new File(["..."], "avatar.png", { type: "image/png" }));

const response = await fetch("https://example.com/upload", {
  method: "POST",
  body: form,
});

WebSocket

WebSocket is available globally for connecting to WebSocket servers.
const ws = new WebSocket("wss://echo.websocket.org");

ws.addEventListener("open", () => {
  ws.send("hello server");
});

ws.addEventListener("message", (event) => {
  console.log("received:", event.data);
  ws.close();
});
Bun also has a high-performance server-side WebSocket API via Bun.serve. See the WebSockets page.

Web Crypto

The Web Crypto API (crypto, SubtleCrypto, CryptoKey) is available globally.
// Generate a random UUID
const id = crypto.randomUUID();

// Fill a buffer with random bytes
const buffer = new Uint8Array(32);
crypto.getRandomValues(buffer);

// Use SubtleCrypto for hashing
const encoder = new TextEncoder();
const data = encoder.encode("hello world");
const hash = await crypto.subtle.digest("SHA-256", data);
const hex = Buffer.from(hash).toString("hex");
console.log(hex);
// Generate an AES-GCM key
const key = await crypto.subtle.generateKey(
  { name: "AES-GCM", length: 256 },
  true,
  ["encrypt", "decrypt"],
);

Encoding

TextEncoder and TextDecoder convert between strings and binary data. atob and btoa handle base64.
const encoder = new TextEncoder();
const bytes = encoder.encode("hello"); // Uint8Array

const decoder = new TextDecoder();
const str = decoder.decode(bytes); // "hello"

// Base64
const b64 = btoa("hello world");   // "aGVsbG8gd29ybGQ="
const raw = atob(b64);             // "hello world"

Timers

All standard timer functions are globally available.
// Run after a delay
const id = setTimeout(() => console.log("fired"), 1000);
clearTimeout(id);

// Run repeatedly
const interval = setInterval(() => console.log("tick"), 500);
clearInterval(interval);

// Run after current task, before next I/O event
setImmediate(() => console.log("immediate"));

// Enqueue a microtask
queueMicrotask(() => console.log("microtask"));

Console

console matches the browser and Node.js APIs.
console.log("plain log");
console.info("info message");
console.warn("warning");
console.error("error message");
console.table([{ name: "alice", age: 30 }, { name: "bob", age: 25 }]);
console.time("label");
// ... work ...
console.timeEnd("label");

Performance

performance is available globally for measuring timing.
const start = performance.now();
// ... do work ...
const end = performance.now();
console.log(`elapsed: ${end - start}ms`);

performance.mark("start");
// ... do work ...
performance.mark("end");
performance.measure("my task", "start", "end");

Events

The full event system is implemented.
const target = new EventTarget();

target.addEventListener("greet", (event) => {
  console.log((event as CustomEvent).detail); // "hello"
});

target.dispatchEvent(new CustomEvent("greet", { detail: "hello" }));

Workers

Worker (Web Workers API) is available for running JavaScript on background threads.
const worker = new Worker(new URL("./worker.ts", import.meta.url));

worker.postMessage({ type: "ping" });

worker.onmessage = (event) => {
  console.log(event.data); // response from worker
};
For a full guide on workers and inter-thread communication, see the Workers page.

Hashing and passwords

Bun.hash()

Bun.hash() provides fast non-cryptographic hashing using Wyhash (default) and several other algorithms:
Bun.hash("hello world");         // number (Wyhash)
Bun.hash.wyhash("hello world");  // number
Bun.hash.crc32("hello world");   // number
Bun.hash.adler32("hello world"); // number
Bun.hash.cityHash32("data");     // number
Bun.hash.cityHash64("data");     // bigint
Bun.hash.murmur32v3("data");     // number
Bun.hash.murmur64v2("data");     // bigint
All variants accept string, ArrayBuffer, TypedArray, or DataView. An optional seed can be passed as the second argument.

Bun.password

Bun.password provides secure password hashing using Argon2 (default) or bcrypt:
const password = "super-secure-pa$$word";

// Hash using argon2id (default, recommended)
const hash = await Bun.password.hash(password);
// => "$argon2id$v=19$m=65536,t=2,p=1$..."

// Verify a password against its hash
const isMatch = await Bun.password.verify(password, hash);
// => true
Configure the algorithm and its parameters:
// Argon2 with custom parameters
const argonHash = await Bun.password.hash(password, {
  algorithm: "argon2id", // "argon2id" | "argon2i" | "argon2d"
  memoryCost: 4,         // memory in kibibytes
  timeCost: 3,           // number of iterations
});

// bcrypt
const bcryptHash = await Bun.password.hash(password, {
  algorithm: "bcrypt",
  cost: 10, // 4–31
});
verify() auto-detects the algorithm from the hash format (PHC for Argon2, MCF for bcrypt).

Supported APIs reference

CategoryAPIs
HTTPfetch, Request, Response, Headers, AbortController, AbortSignal
URLsURL, URLSearchParams
StreamsReadableStream, WritableStream, TransformStream, ByteLengthQueuingStrategy, CountQueuingStrategy
BlobBlob, File, FormData
WebSocketsWebSocket
Cryptocrypto, SubtleCrypto, CryptoKey, Crypto
EncodingTextEncoder, TextDecoder, TextEncoderStream, TextDecoderStream, atob, btoa
TimerssetTimeout, clearTimeout, setInterval, clearInterval, setImmediate, clearImmediate
MicrotasksqueueMicrotask
EventsEventTarget, Event, CustomEvent, ErrorEvent, CloseEvent, MessageEvent
WorkersWorker, MessageChannel, MessagePort, BroadcastChannel
Debuggingconsole, performance
User interactionalert, confirm, prompt (intended for interactive CLIs)
CompressionCompressionStream, DecompressionStream
RealmsShadowRealm
JSONJSON
OtherstructuredClone, reportError, WebAssembly

Build docs developers (and LLMs) love