fetch
standard, with some extensions to meet the needs of server-side JavaScript.
Bun also implements node:http
, but fetch
is generally recommended instead.
Sending an HTTP request
To send an HTTP request, usefetch
fetch
also works with HTTPS URLs.
fetch
a Request
object.
Sending a POST request
To send a POST request, pass an object with themethod
property set to "POST"
.
body
can be a string, a FormData
object, an ArrayBuffer
, a Blob
, and more. See the MDN documentation for more information.
Proxying requests
To proxy a request, pass an object with theproxy
property set to a URL.
Custom headers
To set custom headers, pass an object with theheaders
property set to an object.
Response bodies
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
.
Streaming response bodies
You can use async iterators to stream the response body.ReadableStream
object.
Streaming request bodies
You can also stream data in request bodies using aReadableStream
:
- The data is streamed directly to the network without buffering the entire body in memory
- If the connection is lost, the stream will be canceled
- The
Content-Length
header is not automatically set unless the stream has a known size
- For PUT/POST requests, Bun automatically uses multipart upload
- The stream is consumed in chunks and uploaded in parallel
- Progress can be monitored through the S3 options
Fetching a URL with a timeout
To fetch a URL with a timeout, useAbortSignal.timeout
:
Canceling a request
To cancel a request, use anAbortController
:
Unix domain sockets
To fetch a URL using a Unix domain socket, use theunix: string
option:
TLS
To use a client certificate, use thetls
option:
Custom TLS Validation
To customize the TLS validation, use thecheckServerIdentity
option in tls
net
module.
Disable TLS validation
To disable TLS validation, setrejectUnauthorized
to false
:
Request options
In addition to the standard fetch options, Bun provides several extensions:Protocol support
Beyond HTTP(S), Bun’s fetch supports several additional protocols:S3 URLs - s3://
Bun supports fetching from S3 buckets directly.
File URLs - file://
You can fetch local files using the file:
protocol:
Data URLs - data:
Bun supports the data:
URL scheme:
Blob URLs - blob:
You can fetch blobs using URLs created by URL.createObjectURL()
:
Error handling
Bun’s fetch implementation includes several specific error cases:- Using a request body with GET/HEAD methods will throw an error (which is expected for the fetch API)
- Attempting to use both
proxy
andunix
options together will throw an error - TLS certificate validation failures when
rejectUnauthorized
is true (or undefined) - S3 operations may throw specific errors related to authentication or permissions
Content-Type handling
Bun automatically sets theContent-Type
header for request bodies when not explicitly provided:
- For
Blob
objects, uses the blob’stype
- For
FormData
, sets appropriate multipart boundary
Debugging
To help with debugging, you can passverbose: true
to fetch
:
verbose: boolean
is not part of the Web standard fetch
API and is specific to Bun.
Performance
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.DNS prefetching
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.
DNS caching
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 the DNS caching documentation.
Preconnect to a host
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.
fetch
immediately after fetch.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.
Preconnect at startup
To preconnect to a host at startup, you can pass--fetch-preconnect
:
<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.
Connection pooling & HTTP keep-alive
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.Simultaneous connection limit
By default, Bun limits the maximum number of simultaneousfetch
requests to 256. We do this for several reasons:
- It improves overall system stability. Operating systems have an upper limit on the number of simultaneous open TCP sockets, usually in the low thousands. Nearing this limit causes your entire computer to behave strangely. Applications hang and crash.
- It encourages HTTP Keep-Alive connection reuse. For short-lived HTTP requests, the slowest step is often the initial connection setup. Reusing connections can save a lot of time.
BUN_CONFIG_MAX_HTTP_REQUESTS
environment variable:
Response buffering
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>
Bun.write
to write the response body to a file on disk:
Implementation details
- Connection pooling is enabled by default but can be disabled per-request with
keepalive: false
. The"Connection: close"
header can also be used to disable keep-alive. - Large file uploads are optimized using the operating system’s
sendfile
syscall under specific conditions:- The file must be larger than 32KB
- The request must not be using a proxy
- On macOS, only regular files (not pipes, sockets, or devices) can use
sendfile
- When these conditions aren’t met, or when using S3/streaming uploads, Bun falls back to reading the file into memory
- This optimization is particularly effective for HTTP (not HTTPS) requests where the file can be sent directly from the kernel to the network stack
- S3 operations automatically handle signing requests and merging authentication headers