[> Back to homepage](../readme.md#documentation) ## Stream API Source code: [`source/core/index.ts`](../source/core/index.ts) ### `got.stream(url, options, defaults)` The function above is exposed by the `got` main interface and returns a new instance of `Request`. ### `new Request(url, options, defaults)` **Extends: [`Duplex` stream](https://nodejs.org/api/stream.html#stream_class_stream_duplex)** This constructor takes the same arguments as the Got promise. **Note:** > When piping to [`ServerResponse`](https://nodejs.org/api/http.html#http_class_http_serverresponse), the headers will be automatically copied.\ > When `decompress` is `true` (default) and the response is compressed, the `content-encoding` and `content-length` headers are not copied, as the response is decompressed.\ > To filter which headers are copied, listen to the `response` event and modify `response.headers` before piping to the destination. **Note:** > If the `body`, `json` or `form` option is used, this stream will be read-only. Check [`stream.isReadonly`](#streamisreadonly) to detect this condition. **Note:** > - While `got.post('https://example.com')` resolves, `got.stream.post('https://example.com')` will hang indefinitely until a body is provided. > - If there's no body on purpose, remember to `stream.end()` or set the body option to an empty string. > - `got.stream` does not auto-end for `POST`, `PUT`, `OPTIONS`, `PATCH`, `DELETE`, or `QUERY`. Call `stream.end()` when you are not piping a body. ```js import stream from 'node:stream'; import {pipeline as streamPipeline} from 'node:stream/promises'; import fs from 'node:fs'; import got from 'got'; // This example streams the GET response of a URL to a file. await streamPipeline( got.stream('https://sindresorhus.com'), fs.createWriteStream('index.html') ); // For payload-capable shortcut methods such as POST, PUT, PATCH, DELETE, and QUERY, `got.stream` returns a `stream.Writable`. // This example POSTs the contents of a file to a URL. await streamPipeline( fs.createReadStream('index.html'), got.stream.post('https://sindresorhus.com'), new stream.PassThrough() ); // In order to send one of these methods without a request body, explicitly specify an empty body: await streamPipeline( got.stream.post('https://sindresorhus.com', { body: '' }), new stream.PassThrough() ) ``` Please note that `new stream.PassThrough()` is required in order to catch read errors.\ If it was missing then `pipeline` wouldn't catch any read errors because there would be no stream to pipe to.\ In other words, it would only check errors when writing. **Tip:** > - Avoid `from.pipe(to)` as it doesn't forward errors. ### `stream.options` **Type: [`Options`](2-options.md)** The options used to make the request. ### `stream.response` **Type: [`IncomingMessage`](https://nodejs.org/api/http.html#http_class_http_incomingmessage)** The underlying `IncomingMessage` instance. ### `stream.requestUrl` **Type: [`URL`](https://nodejs.org/api/url.html#url_the_whatwg_url_api)** The current `URL` object in this try. ### `stream.redirectUrls` **Type: [`URL[]`](https://nodejs.org/api/url.html#url_the_whatwg_url_api)** An array of URLs of consecutive requests. ### `stream.retryCount` **Type: `number`** The current retry count. **Note:** > - Must be overriden when retrying. ### `stream.ip` **Type: `string | undefined`** The destination IP address. ### `stream.isAborted` **Type: `boolean`** Whether the request has been aborted or not. ### `stream.socket` **Type: `net.Socket | tls.Socket | undefined`** The socket used for this particular request. ### `stream.downloadProgress` **Type: [`Progress`](typescript.md#progress)** An object representing how much data have been downloaded. ### `stream.uploadProgress` **Type: [`Progress`](typescript.md#progress)** An object representing how much data have been uploaded. Granular upload progress is automatically supported for non-stream `body` (string/Uint8Array/TypedArray), `json`, and `form` options. For Node.js streams, you can use the [`chunk-data`](https://github.com/sindresorhus/chunk-data) package to get granular progress: ```js import fs from 'node:fs'; import got from 'got'; import {chunkFromAsync} from 'chunk-data'; const filePath = 'large-file.bin'; const stream = fs.createReadStream(filePath); const size = fs.statSync(filePath).size; await got.post('https://httpbin.org/anything', { body: chunkFromAsync(stream, 65_536), headers: { 'content-length': size } }) .on('uploadProgress', progress => { console.log(progress); }); ``` ### `stream.timings` **Type: [`Timings`](typescript.md#timings)** An object representing performance information. To generate the timings, Got uses the [`http-timer`](https://github.com/szmarczak/http-timer) package. ### `stream.isFromCache` **Type: `boolean | undefined`** Whether the response has been fetched from cache. ### `stream.reusedSocket` **Type: `boolean`** Whether the socket was used for other previous requests. ### `stream.isReadonly` **Type: `boolean`** Whether the stream is read-only. Returns `true` when `body`, `json`, or `form` options are provided. ## Events ### `stream.on('response', …)` #### `response` **Type: [`PlainResponse`](typescript.md#plainresponse)** This is emitted when a HTTP response is received. ```js import {pipeline as streamPipeline} from 'node:stream/promises'; import {createWriteStream} from 'node:fs'; import got from 'got'; const readStream = got.stream('http://example.com/image.png', {throwHttpErrors: false}); const onError = error => { // Do something with it. }; readStream.on('response', async response => { if (response.headers.age > 3600) { console.log('Failure - response too old'); readStream.destroy(); // Destroy the stream to prevent hanging resources. return; } // Prevent `onError` being called twice. readStream.off('error', onError); try { await streamPipeline( readStream, createWriteStream('image.png') ); console.log('Success'); } catch (error) { onError(error); } }); readStream.once('error', onError); ``` ### Example: Reading HTTP error response bodies By default, Got throws HTTP errors before the stream becomes readable. To read error response bodies: ```js import {pipeline as streamPipeline} from 'node:stream/promises'; import got from 'got'; const stream = got.stream('https://httpbin.org/status/404', { throwHttpErrors: false }); stream.on('response', response => { if (!response.ok) { console.log(`HTTP Error: ${response.statusCode}`); // Stream is readable, you can pipe or read the error body } }); await streamPipeline(stream, process.stdout); ``` **Example: Filter headers when proxying to ServerResponse** ```js import {pipeline as streamPipeline} from 'node:stream/promises'; import got from 'got'; import express from 'express'; const app = express(); // Allowlist specific headers when proxying app.get('/proxy', async (request, response) => { await streamPipeline( got.stream(request.query.url).on('response', upstreamResponse => { // Only allow specific headers for (const header of Object.keys(upstreamResponse.headers)) { if (!['content-type', 'content-length'].includes(header.toLowerCase())) { delete upstreamResponse.headers[header]; } } }), response ); }); ``` ### `stream.on('downloadProgress', …)` #### `progress` **Type: [`Progress`](typescript.md#progress)** This is emitted on every time `stream.downloadProgress` is updated. ### `stream.on('uploadProgress', …)` #### `progress` **Type: [`Progress`](typescript.md#progress)** This is emitted on every time `stream.uploadProgress` is updated. ### `stream.on('retry', …)` To enable retrying when using streams, a retry handler must be attached. When this event is emitted, you should reset the stream you were writing to and prepare the body again. **Note:** > - [`HTTPError`s](./8-errors.md#httperror) cannot be retried if [`options.throwHttpErrors`](./2-options.md#throwhttperrors) is `false`. > This is because stream data is saved to `error.response.body` and streams can be read only once. > - For the Promise API, there is no such limitation. > - If you need to read HTTP error response bodies without retry, see [Reading HTTP error response bodies](#example-reading-http-error-response-bodies). #### `retryCount` **Type: `number`** The current retry count. #### `error` **Type: [`RequestError`](8-errors.md#requesterror)** The error that caused this retry. #### `createRetryStream` **Type: `(options?: OptionsInit) => Request`** ```js import fs from 'node:fs'; import got from 'got'; let writeStream; const fn = retryStream => { const options = { headers: { foo: 'bar' }, }; const stream = retryStream ?? got.stream('https://example.com', options); if (writeStream) { writeStream.destroy(); } writeStream = fs.createWriteStream('example-com.html'); stream.pipe(writeStream); // If you don't attach the listener, it will NOT make a retry. // It automatically checks the listener count so it knows whether to retry or not :) stream.once('retry', (retryCount, error, createRetryStream) => { fn(createRetryStream()); // or: fn(createRetryStream(optionsToMerge)) }); }; fn(); ``` ### `stream.on('redirect', …)` #### `updatedOptions` **Type: [`Options`](2-options.md)** The new options used to make the next request. #### `response` **Type: [`IncomingMessage`](https://nodejs.org/api/http.html#http_class_http_incomingmessage)** The `IncomingMessage` instance the redirect came from. ## Internal usage These are the functions used internally by Got.\ Other non-documented functions are private and should not be accessible. ### `stream.flush()` This function is executed automatically by Got. It marks the current stream as ready. If an error occurs before `stream.flush()` is called, it's thrown immediately after `stream.flush()`. ### `stream._beforeError(error)` This function is called instead of `stream.destroy(error)`, required in order to execute async logic, such as reading the response (e.g. when `ERR_NON_2XX_3XX_RESPONSE` occurs). ### `stream._noPipe` **Type: `boolean`** Whether piping is disabled or not. This property is used by the Promise API. --- ## `Response` Source code: [`source/core/response.ts`](../source/core/response.ts) **Extends: [`IncomingMessage`](https://nodejs.org/api/http.html#http_class_http_incomingmessage)** ### `requestUrl` **Type: `URL`** The original request URL. It is the first argument when calling `got(…)`. ### `redirectUrls` **Type: `URL[]`** The redirect URLs. ### `request` **Type: `Request`** The underlying Got stream. ### `ip` **Type: `string`** The server's IP address. **Note:** > - Not available when the response is cached. ### `isFromCache` **Type: `boolean`** Whether the response comes from cache or not. ### `ok` **Type: `boolean`** Whether the response was successful **Note:** > - A request is successful when the status code of the final request is `2xx` or `3xx`. > - When [following redirects](2-options.md#followredirect), a request is successful **only** when the status code of the final request is `2xx`. > - `304` responses are always considered successful. > - Got throws automatically when `response.ok` is `false` and `throwHttpErrors` is `true`. > - **To read HTTP error response bodies with streams**, set `throwHttpErrors: false` and check `response.ok` in the `response` event handler. [See example above](#example-reading-http-error-response-bodies). ### `statusCode` **Type: `number`** The [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status). ### `url` **Type: `string`** The final URL after all redirects. ### `timings` **Type: [`Timings`](typescript.md#timings)** The same as `request.timings`. ### `retryCount` **Type: `number`** The same as `request.retryCount`. ### `rawBody` **Type: `Uint8Array`** **Note:** > - This property is only accessible when using Promise API. The raw response body bytes. ### `body` **Type: `unknown`** **Note:** > - This property is only accessible when using Promise API. The parsed response body. ### `aborted` **Type: `boolean`** The same as `request.aborted`. ### `complete` **Type: `boolean`** If `true`, the response has been fully parsed. ### `socket` **Type: `net.Socket | tls.TLSSocket`** The same as `request.socket`. ### `headers` **Type: `object`** The [response headers](https://nodejs.org/api/http.html#http_message_headers). ### `statusMessage` **Type: `string`** The status message corresponding to the status code.