Intro
What is Bun?
Installation
Quickstart
TypeScript
Templating
bun init
bun create
Runtime
bun run
File types
TypeScript
JSX
Environment variables
Bun APIs
Web APIs
Node.js compatibility
Single-file executable
Plugins
Watch mode
Module resolution
Auto-install
bunfig.toml
Debugger
Framework APISOON
Package manager
bun install
bun add
bun remove
bun update
bun publish
bun outdated
bun link
bun pm
Global cache
Workspaces
Lifecycle scripts
Filter
Lockfile
Scopes and registries
Overrides and resolutions
Patch dependencies
.npmrc support
Bundler
Bun.build
HTML & static sites
CSS
Fullstack Dev Server
Hot reloading
Loaders
Plugins
Macros
vs esbuild
Test runner
bun test
Writing tests
Watch mode
Lifecycle hooks
Mocks
Snapshots
Dates and times
DOM testing
Code coverage
Package runner
bunx
API
HTTP server
HTTP client
WebSockets
Workers
Binary data
Streams
SQL
S3 Object Storage
File I/O
import.meta
SQLite
FileSystemRouter
TCP sockets
UDP sockets
Globals
$ Shell
Child processes
HTMLRewriter
Hashing
Console
Cookie
FFI
C Compiler
Testing
Utils
Node-API
Glob
DNS
Semver
Color
Transpiler
Project
Roadmap
Benchmarking
Contributing
Building Windows
Bindgen
License
Search the docs...
/
Intro
What is Bun?
Installation
Quickstart
TypeScript
Templating
bun init
bun create
Runtime
bun run
File types
TypeScript
JSX
Environment variables
Bun APIs
Web APIs
Node.js compatibility
Single-file executable
Plugins
Watch mode
Module resolution
Auto-install
bunfig.toml
Debugger
Framework APISOON
Package manager
bun install
bun add
bun remove
bun update
bun publish
bun outdated
bun link
bun pm
Global cache
Workspaces
Lifecycle scripts
Filter
Lockfile
Scopes and registries
Overrides and resolutions
Patch dependencies
.npmrc support
Bundler
Bun.build
HTML & static sites
CSS
Fullstack Dev Server
Hot reloading
Loaders
Plugins
Macros
vs esbuild
Test runner
bun test
Writing tests
Watch mode
Lifecycle hooks
Mocks
Snapshots
Dates and times
DOM testing
Code coverage
Package runner
bunx
API
HTTP server
HTTP client
WebSockets
Workers
Binary data
Streams
SQL
S3 Object Storage
File I/O
import.meta
SQLite
FileSystemRouter
TCP sockets
UDP sockets
Globals
$ Shell
Child processes
HTMLRewriter
Hashing
Console
Cookie
FFI
C Compiler
Testing
Utils
Node-API
Glob
DNS
Semver
Color
Transpiler
Project
Roadmap
Benchmarking
Contributing
Building Windows
Bindgen
License
Bun implements the WHATWGfetch
standard, with some extensions to meet the needs of server-side JavaScript.
Bun also implementsnode:http
, butfetch
is generally recommended instead.
To send an HTTP request, usefetch
const response=awaitfetch("http://example.com");console.log(response.status);// => 200const text=await response.text();// or response.json(), response.formData(), etc.
fetch
also works with HTTPS URLs.
const response=awaitfetch("https://example.com");
You can also passfetch
aRequest
object.
const request=newRequest("http://example.com", { method:"POST", body:"Hello, world!",});const response=awaitfetch(request);
To send a POST request, pass an object with themethod
property set to"POST"
.
const response=awaitfetch("http://example.com", { method:"POST", body:"Hello, world!",});
body
can be a string, aFormData
object, anArrayBuffer
, aBlob
, and more. See theMDN documentation for more information.
To proxy a request, pass an object with theproxy
property set to a URL.
const response=awaitfetch("http://example.com", { proxy:"http://proxy.com",});
To set custom headers, pass an object with theheaders
property set to an object.
const response=awaitfetch("http://example.com", { headers: {"X-Custom-Header":"value", },});
You can also set headers using theHeaders object.
const headers=newHeaders();headers.append("X-Custom-Header","value");const response=awaitfetch("http://example.com", { headers,});
To read the response body, use one of the following methods:
response.text(): Promise<string>
: Returns a promise that resolves with the response body as a string.response.json(): Promise<any>
: Returns a promise that resolves with the response body as a JSON object.response.formData(): Promise<FormData>
: Returns a promise that resolves with the response body as aFormData
object.response.bytes(): Promise<Uint8Array>
: Returns a promise that resolves with the response body as aUint8Array
.response.arrayBuffer(): Promise<ArrayBuffer>
: Returns a promise that resolves with the response body as anArrayBuffer
.response.blob(): Promise<Blob>
: Returns a promise that resolves with the response body as aBlob
.You can use async iterators to stream the response body.
const response=awaitfetch("http://example.com");forawait (const chunkof response.body) { console.log(chunk);}
You can also more directly access theReadableStream
object.
const response=awaitfetch("http://example.com");const stream= response.body;const reader= stream.getReader();const { value, done }=await reader.read();
You can also stream data in request bodies using aReadableStream
:
const stream=newReadableStream({start(controller) { controller.enqueue("Hello"); controller.enqueue(""); controller.enqueue("World"); controller.close(); },});const response=awaitfetch("http://example.com", { method:"POST", body: stream,});
When using streams with HTTP(S):
Content-Length
header is not automatically set unless the stream has a known sizeWhen using streams with S3:
To fetch a URL with a timeout, useAbortSignal.timeout
:
const response=awaitfetch("http://example.com", { signal: AbortSignal.timeout(1000),});
To cancel a request, use anAbortController
:
const controller=newAbortController();const response=awaitfetch("http://example.com", { signal: controller.signal,});controller.abort();
To fetch a URL using a Unix domain socket, use theunix: string
option:
const response=awaitfetch("https://hostname/a/path", { unix:"/var/run/path/to/unix.sock", method:"POST", body:JSON.stringify({ message:"Hello from Bun!" }), headers: {"Content-Type":"application/json", },});
To use a client certificate, use thetls
option:
awaitfetch("https://example.com", { tls: { key: Bun.file("/path/to/key.pem"), cert: Bun.file("/path/to/cert.pem"),// ca: [Bun.file("/path/to/ca.pem")], },});
To customize the TLS validation, use thecheckServerIdentity
option intls
awaitfetch("https://example.com", { tls: {checkServerIdentity: (hostname,peerCertificate)=> {// Return an Error if the certificate is invalid }, },});
This is similar to how it works in Node'snet
module.
To disable TLS validation, setrejectUnauthorized
tofalse
:
awaitfetch("https://example.com", { tls: { rejectUnauthorized:false, },});
This is especially useful to avoid SSL errors when using self-signed certificates, but this disables TLS validation and should be used with caution.
In addition to the standard fetch options, Bun provides several extensions:
const response=awaitfetch("http://example.com", {// Control automatic response decompression (default: true) decompress:true,// Disable connection reuse for this request keepalive:false,// Debug logging level verbose:true,// or "curl" for more detailed output});
Beyond HTTP(S), Bun's fetch supports several additional protocols:
s3://
Bun supports fetching from S3 buckets directly.
// Using environment variables for credentialsconst response=awaitfetch("s3://my-bucket/path/to/object");// Or passing credentials explicitlyconst response=awaitfetch("s3://my-bucket/path/to/object", { s3: { accessKeyId:"YOUR_ACCESS_KEY", secretAccessKey:"YOUR_SECRET_KEY", region:"us-east-1", },});
Note: Only PUT and POST methods support request bodies when using S3. For uploads, Bun automatically uses multipart upload for streaming bodies.
You can read more about Bun's S3 support in theS3 documentation.
file://
You can fetch local files using thefile:
protocol:
const response=awaitfetch("file:///path/to/file.txt");const text=await response.text();
On Windows, paths are automatically normalized:
// Both work on Windowsconst response=awaitfetch("file:///C:/path/to/file.txt");const response2=awaitfetch("file:///c:/path\\to/file.txt");
data:
Bun supports thedata:
URL scheme:
const response=awaitfetch("data:text/plain;base64,SGVsbG8sIFdvcmxkIQ==");const text=await response.text();// "Hello, World!"
blob:
You can fetch blobs using URLs created byURL.createObjectURL()
:
const blob=newBlob(["Hello, World!"], { type:"text/plain" });const url=URL.createObjectURL(blob);const response=awaitfetch(url);
Bun's fetch implementation includes several specific error cases:
proxy
andunix
options together will throw an errorrejectUnauthorized
is true (or undefined)Bun automatically sets theContent-Type
header for request bodies when not explicitly provided:
Blob
objects, uses the blob'stype
FormData
, sets appropriate multipart boundaryapplication/json
To help with debugging, you can passverbose: true
tofetch
:
const response=awaitfetch("http://example.com", { verbose:true,});
This will print the request and response headers to your terminal:
[fetch]> HTTP/1.1 GET http://example.com/[fetch]> Connection: keep-alive[fetch]> User-Agent: Bun/1.2.7[fetch]> Accept:*/*[fetch]> Host: example.com[fetch]> Accept-Encoding: gzip, deflate, br[fetch]< 200 OK[fetch]< Content-Encoding: gzip[fetch]< Age: 201555[fetch]< Cache-Control: max-age=604800[fetch]< Content-Type: text/html; charset=UTF-8[fetch]< Date: Sun, 21 Jul 2024 02:41:14 GMT[fetch]< Etag:"3147526947+gzip"[fetch]< Expires: Sun, 28 Jul 2024 02:41:14 GMT[fetch]< Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT[fetch]< Server: ECAcc (sac/254F)[fetch]< Vary: Accept-Encoding[fetch]< X-Cache: HIT[fetch]< Content-Length: 648
Note:verbose: boolean
is not part of the Web standardfetch
API and is specific to Bun.
Before an HTTP request can be sent, the DNS lookup must be performed. This can take a significant amount of time, especially if the DNS server is slow or the network connection is poor.
After the DNS lookup, the TCP socket must be connected and the TLS handshake might need to be performed. This can also take a significant amount of time.
After the request completes, consuming the response body can also take a significant amount of time and memory.
At every step of the way, Bun provides APIs to help you optimize the performance of your application.
To prefetch a DNS entry, you can use thedns.prefetch
API. This API is useful when you know you'll need to connect to a host soon and want to avoid the initial DNS lookup.
import { dns }from"bun";dns.prefetch("bun.sh");
By default, Bun caches and deduplicates DNS queries in-memory for up to 30 seconds. You can see the cache stats by callingdns.getCacheStats()
:
To learn more about DNS caching in Bun, see theDNS caching documentation.
To preconnect to a host, you can use thefetch.preconnect
API. This API is useful when you know you'll need to connect to a host soon and want to start the initial DNS lookup, TCP socket connection, and TLS handshake early.
import { fetch }from"bun";fetch.preconnect("https://bun.sh");
Note: callingfetch
immediately afterfetch.preconnect
will not make your request faster. Preconnecting only helps if you know you'll need to connect to a host soon, but you're not ready to make the request yet.
To preconnect to a host at startup, you can pass--fetch-preconnect
:
bun --fetch-preconnect https://bun.sh ./my-script.ts
This is sort of like<link rel="preconnect">
in HTML.
This feature is not implemented on Windows yet. If you're interested in using this feature on Windows, please file an issue and we can implement support for it on Windows.
Bun automatically reuses connections to the same host. This is known as connection pooling. This can significantly reduce the time it takes to establish a connection. You don't need to do anything to enable this; it's automatic.
By default, Bun limits the maximum number of simultaneousfetch
requests to 256. We do this for several reasons:
When the limit is exceeded, the requests are queued and sent as soon as the next request ends.
You can increase the maximum number of simultaneous connections via theBUN_CONFIG_MAX_HTTP_REQUESTS
environment variable:
BUN_CONFIG_MAX_HTTP_REQUESTS=512 bun ./my-script.ts
The max value for this limit is currently set to 65,336. The maximum port number is 65,535, so it's quite difficult for any one computer to exceed this limit.
Bun goes to great lengths to optimize the performance of reading the response body. The fastest way to read the response body is to use one of these methods:
response.text(): Promise<string>
response.json(): Promise<any>
response.formData(): Promise<FormData>
response.bytes(): Promise<Uint8Array>
response.arrayBuffer(): Promise<ArrayBuffer>
response.blob(): Promise<Blob>
You can also useBun.write
to write the response body to a file on disk:
import { write }from"bun";awaitwrite("output.txt", response);
keepalive: false
. The"Connection: close"
header can also be used to disable keep-alive.sendfile
syscall under specific conditions:sendfile
Note: Many of these features are Bun-specific extensions to the standard fetch API.