# Technical Documentation: sindresorhus/got > ℹ️ **Provenance:** Hybrid Fusion: `sindresorhus/got` (README + 10 In-Tree Chapters) · [CodeWiki Reference](https://codewiki.google/github.com/sindresorhus/got) · Recency: Active (< 180 days) ## 1. Project Overview & Quickstart (sindresorhus/got) ## 2. In-Tree Documentation Chapters (sindresorhus/got) ## File: readme.md **Fast remote container builds and GitHub Actions runners.**
> Human-friendly and powerful HTTP request library for Node.js [](https://npmjs.com/got) [](https://packagephobia.com/result?p=got) [See how Got compares to other HTTP libraries](#comparison) --- **You probably want [Ky](https://github.com/sindresorhus/ky) instead, by the same people. It's smaller, works in the browser too, and is more stable since it's built on [`Fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API). Or [fetch-extras](https://github.com/sindresorhus/fetch-extras) for simple needs.** --- **Support questions should be asked [here](https://github.com/sindresorhus/got/discussions).** ## Install ```sh npm install got ``` **Warning:** This package is native [ESM](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) and no longer provides a CommonJS export. If your project uses CommonJS, you will have to [convert to ESM](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c). Please don't open issues for questions regarding CommonJS / ESM. **Got v11 is no longer maintained and we will not accept any backport requests.** ## Take a peek **A [quick start](documentation/quick-start.md) guide is available.** ### JSON mode Got has a dedicated option for handling JSON payload.\ Furthermore, the promise exposes a `.json()` function that returns `Promise`. ```js import got from 'got'; const {data} = await got.post('https://httpbin.org/anything', { json: { hello: 'world' } }).json(); console.log(data); //=> {"hello": "world"} ``` For advanced JSON usage, check out the [`parseJson`](documentation/2-options.md#parsejson) and [`stringifyJson`](documentation/2-options.md#stringifyjson) options. **For more useful tips like this, visit the [Tips](documentation/tips.md) page.** ## Highlights - [Used by 10K+ packages and 5M+ repos](https://github.com/sindresorhus/got/network/dependents) - [Actively maintained](https://github.com/sindresorhus/got/graphs/contributors) - [Trusted by many companies](#widely-used) ## Documentation By default, Got will retry on failure. To disable this option, set [`options.retry.limit`](documentation/7-retry.md#retry) to 0. #### Main API - [x] [Promise API](documentation/1-promise.md) - [x] [Options](documentation/2-options.md) - [x] [Stream API](documentation/3-streams.md) - [x] [Pagination API](documentation/4-pagination.md) - [x] [Advanced HTTPS API](documentation/5-https.md) - [x] [HTTP/2 support](documentation/2-options.md#http2) - [x] [`Response` class](documentation/3-streams.md#response-2) #### Timeouts and retries - [x] [Advanced timeout handling](documentation/6-timeout.md) - [x] [Retries on failure](documentation/7-retry.md) - [x] [Errors with metadata](documentation/8-errors.md) #### Advanced creation - [x] [Hooks](documentation/9-hooks.md) - [x] [Instances](documentation/10-instances.md) - [x] [Progress events & other events](documentation/3-streams.md#events) - [x] [Plugins](documentation/lets-make-a-plugin.md) - [x] [Compose](documentation/examples/advanced-creation.js) #### Cache, Proxy and UNIX sockets - [x] [RFC 7234 compliant caching](documentation/cache.md) - [x] [Proxy support](documentation/tips.md#proxying) - [x] [Unix Domain Sockets](documentation/2-options.md#enableunixsockets) #### Integration - [x] [Diagnostics Channel](documentation/diagnostics-channel.md) - [x] [TypeScript support](documentation/typescript.md) - [x] [AWS](documentation/tips.md#aws) - [x] [Testing](documentation/tips.md#testing) --- ### Migration guides - [Request migration guide](documentation/migration-guides/request.md) - [*(Note that Request is unmaintained)*](https://github.com/request/request/issues/3142) - [Axios](documentation/migration-guides/axios.md) - [Node.js](documentation/migration-guides/nodejs.md) ## Got plugins - [`got4aws`](https://github.com/SamVerschueren/got4aws) - Got convenience wrapper to interact with AWS v4 signed APIs - [`gh-got`](https://github.com/sindresorhus/gh-got) - Got convenience wrapper to interact with the GitHub API - [`gl-got`](https://github.com/singapore/gl-got) - Got convenience wrapper to interact with the GitLab API - [`gotql`](https://github.com/khaosdoctor/gotql) - Got convenience wrapper to interact with GraphQL using JSON-parsed queries instead of strings - [`got-fetch`](https://github.com/alexghr/got-fetch) - Got with a [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) interface - [`got-scraping`](https://github.com/apify/got-scraping) - Got wrapper specifically designed for web scraping purposes - [`got-ssrf`](https://github.com/JaneJeon/got-ssrf) - Got wrapper to protect server-side requests against SSRF attacks ## Comparison | | `got` | [`node-fetch`][n0] | [`ky`][k0] | [`axios`][a0] | [`superagent`][s0] | |-----------------------|:-------------------:|:--------------------:|:------------------------:|:------------------:|:----------------------:| | HTTP/2 support | :heavy_check_mark: | :x: | :heavy_check_mark: | :x: | :heavy_check_mark:\*\* | | Browser support | :x: | :heavy_check_mark:\* | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | Promise API | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | Stream API | :heavy_check_mark: | Node.js only | :x: | :x: | :heavy_check_mark: | | Pagination API | :heavy_check_mark: | :x: | :x: | :x: | :x: | | Request aborting | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | RFC 7234 caching | :heavy_check_mark: | :x: | :x: | :x: | :x: | | Cookies (out-of-the-box) | :heavy_check_mark: | :x: | :x: | :x: | :x: | | Follows redirects | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | Retries on failure | :heavy_check_mark: | :x: | :heavy_check_mark: | :x: | :heavy_check_mark: | | Progress events | :heavy_check_mark: | :x: | :heavy_check_mark: | Browser only | :heavy_check_mark: | | Handles gzip/deflate | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | Advanced timeouts | :heavy_check_mark: | :x: | :x: | :x: | :x: | | Timings | :heavy_check_mark: | :x: | :x: | :x: | :x: | | Errors with metadata | :heavy_check_mark: | :x: | :heavy_check_mark: | :heavy_check_mark: | :x: | | JSON mode | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | Custom defaults | :heavy_check_mark: | :x: | :heavy_check_mark: | :heavy_check_mark: | :x: | | Composable | :heavy_check_mark: | :x: | :x: | :x: | :heavy_check_mark: | | Hooks | :heavy_check_mark: | :x: | :heavy_check_mark: | :heavy_check_mark: | :x: | | Issues open | [![][gio]][g1] | [![][nio]][n1] | [![][kio]][k1] | [![][aio]][a1] | [![][sio]][s1] | | Issues closed | [![][gic]][g2] | [![][nic]][n2] | [![][kic]][k2] | [![][aic]][a2] | [![][sic]][s2] | | Downloads | [![][gd]][g3] | [![][nd]][n3] | [![][kd]][k3] | [![][ad]][a3] | [![][sd]][s3] | | Coverage | TBD | [![][nc]][n4] | [![][kc]][k4] | [![][ac]][a4] | [![][sc]][s4] | | Build | [![][gb]][g5] | [![][nb]][n5] | [![][kb]][k5] | [![][ab]][a5] | [![][sb]][s5] | | Bugs | [![][gbg]][g6] | [![][nbg]][n6] | [![][kbg]][k6] | [![][abg]][a6] | [![][sbg]][s6] | | Dependents | [![][gdp]][g7] | [![][ndp]][n7] | [![][kdp]][k7] | [![][adp]][a7] | [![][sdp]][s7] | | Install size | [![][gis]][g8] | [![][nis]][n8] | [![][kis]][k8] | [![][ais]][a8] | [![][sis]][s8] | | GitHub stars | [![][gs]][g9] | [![][ns]][n9] | [![][ks]][k9] | [![][as]][a9] | [![][ss]][s9] | | TypeScript support | [![][gts]][g10] | [![][nts]][n10] | [![][kts]][k10] | [![][ats]][a10] | [![][sts]][s11] | | Last commit | [![][glc]][g11] | [![][nlc]][n11] | [![][klc]][k11] | [![][alc]][a11] | [![][slc]][s11] | \* It's almost API compatible with the browser `fetch` API.\ \*\* Need to switch the protocol manually. Doesn't accept PUSH streams and doesn't reuse HTTP/2 sessions.\ :sparkle: Almost-stable feature, but the API may change. Don't hesitate to try it out!\ :grey_question: Feature in early stage of development. Very experimental. [k0]: https://github.com/sindresorhus/ky [n0]: https://github.com/node-fetch/node-fetch [a0]: https://github.com/axios/axios [s0]: https://github.com/visionmedia/superagent [gio]: https://img.shields.io/github/issues-raw/sindresorhus/got?color=gray&label [kio]: https://img.shields.io/github/issues-raw/sindresorhus/ky?color=gray&label [nio]: https://img.shields.io/github/issues-raw/bitinn/node-fetch?color=gray&label [aio]: https://img.shields.io/github/issues-raw/axios/axios?color=gray&label [sio]: https://img.shields.io/github/issues-raw/visionmedia/superagent?color=gray&label [g1]: https://github.com/sindresorhus/got/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc [k1]: https://github.com/sindresorhus/ky/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc [n1]: https://github.com/bitinn/node-fetch/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc [a1]: https://github.com/axios/axios/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc [s1]: https://github.com/visionmedia/superagent/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc [gic]: https://img.shields.io/github/issues-closed-raw/sindresorhus/got?color=blue&label [kic]: https://img.shields.io/github/issues-closed-raw/sindresorhus/ky?color=blue&label [nic]: https://img.shields.io/github/issues-closed-raw/bitinn/node-fetch?color=blue&label [aic]: https://img.shields.io/github/issues-closed-raw/axios/axios?color=blue&label [sic]: https://img.shields.io/github/issues-closed-raw/visionmedia/superagent?color=blue&label [g2]: https://github.com/sindresorhus/got/issues?q=is%3Aissue+is%3Aclosed+sort%3Aupdated-desc [k2]: https://github.com/sindresorhus/ky/issues?q=is%3Aissue+is%3Aclosed+sort%3Aupdated-desc [n2]: https://github.com/bitinn/node-fetch/issues?q=is%3Aissue+is%3Aclosed+sort%3Aupdated-desc [a2]: https://github.com/axios/axios/issues?q=is%3Aissue+is%3Aclosed+sort%3Aupdated-desc [s2]: https://github.com/visionmedia/superagent/issues?q=is%3Aissue+is%3Aclosed+sort%3Aupdated-desc [gd]: https://img.shields.io/npm/dm/got?color=darkgreen&label [kd]: https://img.shields.io/npm/dm/ky?color=darkgreen&label [nd]: https://img.shields.io/npm/dm/node-fetch?color=darkgreen&label [ad]: https://img.shields.io/npm/dm/axios?color=darkgreen&label [sd]: https://img.shields.io/npm/dm/superagent?color=darkgreen&label [g3]: https://www.npmjs.com/package/got [k3]: https://www.npmjs.com/package/ky [n3]: https://www.npmjs.com/package/node-fetch [a3]: https://www.npmjs.com/package/axios [s3]: https://www.npmjs.com/package/superagent [kc]: https://img.shields.io/codecov/c/github/sindresorhus/ky?color=0b9062&label [nc]: https://img.shields.io/coveralls/github/bitinn/node-fetch?color=0b9062&label [ac]: https://img.shields.io/coveralls/github/mzabriskie/axios?color=0b9062&label [sc]: https://img.shields.io/codecov/c/github/visionmedia/superagent?color=0b9062&label [k4]: https://codecov.io/gh/sindresorhus/ky [n4]: https://coveralls.io/github/bitinn/node-fetch [a4]: https://coveralls.io/github/mzabriskie/axios [s4]: https://codecov.io/gh/visionmedia/superagent [gb]: https://github.com/sindresorhus/got/actions/workflows/main.yml/badge.svg [kb]: https://github.com/sindresorhus/ky/actions/workflows/main.yml/badge.svg [nb]: https://img.shields.io/travis/bitinn/node-fetch?label [ab]: https://img.shields.io/travis/axios/axios?label [sb]: https://img.shields.io/travis/visionmedia/superagent?label [g5]: https://github.com/sindresorhus/got/actions/workflows/main.yml [k5]: https://github.com/sindresorhus/ky/actions/workflows/main.yml [n5]: https://travis-ci.org/github/bitinn/node-fetch [a5]: https://travis-ci.org/github/axios/axios [s5]: https://travis-ci.org/github/visionmedia/superagent [gbg]: https://img.shields.io/github/issues-raw/sindresorhus/got/bug?color=darkred&label [kbg]: https://img.shields.io/github/issues-raw/sindresorhus/ky/bug?color=darkred&label [nbg]: https://img.shields.io/github/issues-raw/bitinn/node-fetch/bug?color=darkred&label [abg]: https://img.shields.io/github/issues-raw/axios/axios/bug-fix?color=darkred&label [sbg]: https://img.shields.io/github/issues-raw/visionmedia/superagent/Bug?color=darkred&label [g6]: https://github.com/sindresorhus/got/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3Abug [k6]: https://github.com/sindresorhus/ky/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3Abug [n6]: https://github.com/bitinn/node-fetch/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3Abug [a6]: https://github.com/axios/axios/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22bug-fix%22 [s6]: https://github.com/visionmedia/superagent/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3ABug [gdp]: https://badgen.net/npm/dependents/got?color=orange&label [kdp]: https://badgen.net/npm/dependents/ky?color=orange&label [ndp]: https://badgen.net/npm/dependents/node-fetch?color=orange&label [adp]: https://badgen.net/npm/dependents/axios?color=orange&label [sdp]: https://badgen.net/npm/dependents/superagent?color=orange&label [g7]: https://www.npmjs.com/package/got?activeTab=dependents [k7]: https://www.npmjs.com/package/ky?activeTab=dependents [n7]: https://www.npmjs.com/package/node-fetch?activeTab=dependents [a7]: https://www.npmjs.com/package/axios?activeTab=dependents [s7]: https://www.npmjs.com/package/visionmedia?activeTab=dependents [gis]: https://packagephobia.com/badge?p=got [kis]: https://packagephobia.com/badge?p=ky [nis]: https://packagephobia.com/badge?p=node-fetch [ais]: https://packagephobia.com/badge?p=axios [sis]: https://packagephobia.com/badge?p=superagent [g8]: https://packagephobia.com/result?p=got [k8]: https://packagephobia.com/result?p=ky [n8]: https://packagephobia.com/result?p=node-fetch [a8]: https://packagephobia.com/result?p=axios [s8]: https://packagephobia.com/result?p=superagent [gs]: https://img.shields.io/github/stars/sindresorhus/got?color=white&label [ks]: https://img.shields.io/github/stars/sindresorhus/ky?color=white&label [ns]: https://img.shields.io/github/stars/bitinn/node-fetch?color=white&label [as]: https://img.shields.io/github/stars/axios/axios?color=white&label [ss]: https://img.shields.io/github/stars/visionmedia/superagent?color=white&label [g9]: https://github.com/sindresorhus/got [k9]: https://github.com/sindresorhus/ky [n9]: https://github.com/node-fetch/node-fetch [a9]: https://github.com/axios/axios [s9]: https://github.com/visionmedia/superagent [gts]: https://badgen.net/npm/types/got?label [kts]: https://badgen.net/npm/types/ky?label [nts]: https://badgen.net/npm/types/node-fetch?label [ats]: https://badgen.net/npm/types/axios?label [sts]: https://badgen.net/npm/types/superagent?label [g10]: https://github.com/sindresorhus/got [k10]: https://github.com/sindresorhus/ky [n10]: https://github.com/node-fetch/node-fetch [a10]: https://github.com/axios/axios [glc]: https://img.shields.io/github/last-commit/sindresorhus/got?color=gray&label [klc]: https://img.shields.io/github/last-commit/sindresorhus/ky?color=gray&label [nlc]: https://img.shields.io/github/last-commit/bitinn/node-fetch?color=gray&label [alc]: https://img.shields.io/github/last-commit/axios/axios?color=gray&label [slc]: https://img.shields.io/github/last-commit/visionmedia/superagent?color=gray&label [g11]: https://github.com/sindresorhus/got/commits [k11]: https://github.com/sindresorhus/ky/commits [n11]: https://github.com/node-fetch/node-fetch/commits [a11]: https://github.com/axios/axios/commits [s11]: https://github.com/visionmedia/superagent/commits [Click here][InstallSizeOfTheDependencies] to see the install size of the Got dependencies. [InstallSizeOfTheDependencies]: https://packagephobia.com/result?p=@sindresorhus/is@8.0.0,byte-counter@0.1.0,cacheable-request@13.0.18,chunk-data@0.1.0,decompress-response@10.0.0,keyv@5.6.0,lowercase-keys@4.0.1,responselike@4.0.2,type-fest@5.6.0,uint8array-extras@1.5.0 ## Maintainers [](https://sindresorhus.com) | [](https://github.com/szmarczak) ---|--- [Sindre Sorhus](https://sindresorhus.com) | [Szymon Marczak](https://github.com/szmarczak) ## These amazing companies are using Got | | | | | | --- | --- | --- | --- | | | | | | | | | | | > Segment is a happy user of Got! Got powers the main backend API that our app talks to. It's used by our in-house RPC client that we use to communicate with all microservices. > > — [Vadim Demedes](https://github.com/vadimdemedes) > Antora, a static site generator for creating documentation sites, uses Got to download the UI bundle. In Antora, the UI bundle (aka theme) is maintained as a separate project. That project exports the UI as a zip file we call the UI bundle. The main site generator downloads that UI from a URL using Got and streams it to vinyl-zip to extract the files. Those files go on to be used to create the HTML pages and supporting assets. > > — [Dan Allen](https://github.com/mojavelinux) > GetVoIP is happily using Got in production. One of the unique capabilities of Got is the ability to handle Unix sockets which enables us to build a full control interfaces for our docker stack. > > — [Daniel Kalen](https://github.com/danielkalen) > We're using Got inside of Exoframe to handle all the communication between CLI and server. Exoframe is a self-hosted tool that allows simple one-command deployments using Docker. > > — [Tim Ermilov](https://github.com/yamalight) > Karaoke Mugen uses Got to fetch content updates from its online server. > > — [Axel Terizaki](https://github.com/AxelTerizaki) > Renovate uses Got, gh-got and gl-got to send millions of queries per day to GitHub, GitLab, npmjs, PyPi, Packagist, Docker Hub, Terraform, CircleCI, and more. > > — [Rhys Arkins](https://github.com/rarkins) > Resistbot uses Got to communicate from the API frontend where all correspondence ingresses to the officials lookup database in back. > > — [Chris Erickson](https://github.com/chris-erickson) > Natural Cycles is using Got to communicate with all kinds of 3rd-party REST APIs (over 9000!). > > — [Kirill Groshkov](https://github.com/kirillgroshkov) > Microlink is a cloud browser as an API service that uses Got widely as the main HTTP client, serving ~22M requests a month, every time a network call needs to be performed. > > — [Kiko Beats](https://github.com/Kikobeats) > We’re using Got at Radity. Thanks for such an amazing work! > > — [Mirzayev Farid](https://github.com/MirzayevFarid) --- ## File: documentation/migration-guides/axios.md [> Back to homepage](../../readme.md#documentation) ## Migration guides > You may think it's too hard to switch, but it's really not. 🦄 ### Axios Axios is very similar to Got. The difference is that Axios targets browsers first, while Got fully makes use of Node.js features. #### Common options These options remain the same as well: - [`url`](../2-options.md#url) - [`method`](../2-options.md#method) - [`headers`](../2-options.md#headers) - [`maxRedirects`](../2-options.md#maxredirects) - [`decompress`](../2-options.md#decompress) #### Renamed options We deeply care about readability, so we renamed these options: - `httpAgent` → [`agent.http`](../2-options.md#agent) - `httpsAgent` → [`agent.https`](../2-options.md#agent) - `socketPath` → [`url`](../2-options.md#enableunixsockets) - `responseEncoding` → [`encoding`](../2-options.md#encoding) - `auth.username` → [`username`](../2-options.md#username) - `auth.password` → [`password`](../2-options.md#password) - `data` → [`body`](../2-options.md#body) / [`json`](../2-options.md#json) / [`form`](../2-options.md#form) - `params` → [`searchParams`](../2-options.md#searchparams) #### Changes in behavior - `transformRequest` → [`hooks.beforeRequest`](../9-hooks.md#beforerequest) - The API is different. - `transformResponse` → [`hooks.afterResponse`](../9-hooks.md#afterresponse) - The API is different. - `baseUrl` → [`prefixUrl`](../2-options.md#prefixurl) - The `prefixUrl` is prepended to relative string input. Absolute URLs bypass `prefixUrl` by default. Use [`allowAbsoluteUrls: false`](../2-options.md#allowabsoluteurls) to reject absolute URLs when `prefixUrl` is set. - [`timeout`](../6-timeout.md) - This option is now an object. You can now set timeouts on particular events! - [`responseType`](../2-options.md#responsetype) - Accepts `'text'`, `'json'` or `'buffer'`. #### Breaking changes - `onUploadProgress` - This option does not exist. Instead, use [`got(…).on('uploadProgress', …)`](../3-streams.md#uploadprogress). - `onDownloadProgress` - This option does not exist. Instead, use [`got(…).on('downloadProgress', …)`](../3-streams.md#downloadprogress). - `maxContentLength` - This option does not exist. Instead, use [a handler](../examples/advanced-creation.js). - `validateStatus` - This option does not exist. Got automatically validates the status according to [the specification](https://datatracker.ietf.org/doc/html/rfc7231#section-6). - `proxy` - This option does not exist. You need to pass [an `agent`](../tips.md#proxy) instead. - `cancelToken` - Use the [`signal`](../2-options.md#signal) option with [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController). - `paramsSerializer` - This option does not exist. - `maxBodyLength` - This option does not exist. #### Response The response object is different as well: - `response.data` → [`response.body`](../3-streams.md#response-2) - `response.status` → [`response.statusCode`](../3-streams.md#response-2) - `response.statusText` → [`response.statusMessage`](../3-streams.md#response-2) - `response.config` → [`response.request.options`](../3-streams.md#response-2) - [`response.request`](../3-streams.md#response-2) - Returns [a Got stream](../3-streams.md). The `response.headers` object remains the same. #### Interceptors Got offers [hooks](../9-hooks.md) instead, which are more flexible. #### Errors Errors look the same, with the difference `error.request` returns a Got stream. Furthermore, Got provides [more details](../8-errors.md) to make debugging easier. #### Abort Got supports [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) via the [`signal`](../2-options.md#signal) option. #### Convenience methods Convenience methods, such as `axios.get(…)` etc. remain the same: `got.get(…)`. Instead of `axios.create(…)` use `got.extend(…)`. #### You're good to go! Well, you have already come this far :tada:\ Take a look at the [documentation](../../readme.md#documentation). It's worth the time to read it.\ There are [some great tips](../tips.md). If something is unclear or doesn't work as it should, don't hesitate to [open an issue](https://github.com/sindresorhus/got/issues/new/choose). --- ## File: documentation/migration-guides/nodejs.md [> Back to homepage](../../readme.md#documentation) ## Migration guides > You may think it's too hard to switch, but it's really not. 🦄 ### Node.js Let's make a simple request. With Node.js, this is: ```js import http from 'node:http'; const request = http.request('https://httpbin.org/anything', response => { if (response.statusCode >= 400) { request.destroy(new Error()); return; } const chunks = []; let totalLength = 0; response.on('data', chunk => { chunks.push(chunk); totalLength += chunk.length; }); response.once('end', () => { const bytes = new Uint8Array(totalLength); let offset = 0; for (const chunk of chunks) { bytes.set(chunk, offset); offset += chunk.length; } if (response.statusCode >= 400) { const error = new Error(`Unsuccessful response: ${response.statusCode}`); error.body = new TextDecoder().decode(bytes); return; } const text = new TextDecoder().decode(bytes); console.log(text); }); response.once('error', console.error); }); request.once('error', console.error); request.end(); ``` With Got, this becomes: ```js import got from 'got'; try { const {body} = await got('https://httpbin.org/anything'); console.log(body); } catch (error) { console.error(error); } ``` Much cleaner. But what about streams? ```js import http from 'node:http'; import fs from 'node:fs'; const source = fs.createReadStream('article.txt'); const request = http.request('https://httpbin.org/anything', { method: 'POST' }, response => { response.pipe(fs.createWriteStream('httpbin.txt')); }); source.pipe(request); ``` Well, it's easy as that: ```js import got from 'got'; import {pipeline as streamPipeline} from 'node:stream/promises'; import fs from 'node:fs'; await streamPipeline( fs.createReadStream('article.txt'), got.stream.post('https://httpbin.org/anything'), fs.createWriteStream('httpbin.txt') ); ``` The advantage is that Got also handles errors automatically, so you don't have to create custom listeners. Furthermore, Got supports redirects, compression, advanced timeouts, cache, pagination, cookies, hooks, and more! #### What next? Unfortunately Got options differ too much from the Node.js options. It's not possible to provide a brief summary.\ Don't worry, you will learn them fast - they are easy to understand! Every option has an example attached. Take a look at the [documentation](../../readme.md#documentation). It's worth the time to read it.\ There are [some great tips](../tips.md). If something is unclear or doesn't work as it should, don't hesitate to [open an issue](https://github.com/sindresorhus/got/issues/new/choose). --- ## File: documentation/migration-guides/request.md [> Back to homepage](../../readme.md#documentation) ## Migration guides > You may think it's too hard to switch, but it's really not. 🦄 ### Request Let's take the very first example from [Request's readme](https://github.com/request/request#super-simple-to-use): ```js import request from 'request'; request('https://google.com', (error, response, body) => { console.log('error:', error); console.log('statusCode:', response && response.statusCode); console.log('body:', body); }); ``` With Got, it is: ```js import got from 'got'; try { const response = await got('https://google.com'); console.log('statusCode:', response.statusCode); console.log('body:', response.body); } catch (error) { console.log('error:', error); } ``` Looks better now, huh? 😎 #### Common options These Got options are the same as with Request: - [`url`](../2-options.md#url) - [`body`](../2-options.md#body) - [`followRedirect`](../2-options.md#followredirect) - [`encoding`](../2-options.md#encoding) - [`maxRedirects`](../2-options.md#maxredirects) - [`localAddress`](../2-options.md#localaddress) - [`headers`](../2-options.md#headers) - [`createConnection`](../2-options.md#createconnection) - [UNIX sockets](../2-options.md#enableunixsockets): `http://unix:SOCKET:PATH` The `time` option does not exist, assume [it's always true](../6-timeout.md). So if you're familiar with these, you're good to go. #### Renamed options **Note:** > - Got stores HTTPS options inside [`https`](../2-options.md#https). Some of them have been renamed. [Read more](../5-https.md). Readability is very important to us, so we have different names for these options: - `qs` → [`searchParams`](../2-options.md#searchparams) - `strictSSL` → [`rejectUnauthorized`](../2-options.md#rejectunauthorized) - `gzip` → [`decompress`](../2-options.md#decompress) - `jar` → [`cookieJar`](../2-options.md#cookiejar) (accepts [`tough-cookie`](https://github.com/salesforce/tough-cookie) jar) - `jsonReviver` → [`parseJson`](../2-options.md#parsejson) - `jsonReplacer` → [`stringifyJson`](../2-options.md#stringifyjson) #### Changes in behavior - The [`agent` option](../2-options.md#agent) is now an object with `http`, `https` and `http2` properties. - The [`timeout` option](../6-timeout.md) is now an object. You can set timeouts on particular events! - The [`searchParams` option](../2-options.md#searchparams) is always serialized using [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams). - In order to pass a custom query string, provide it with the `url` option.\ `got('https://example.com', {searchParams: {test: ''}})` → `https://example.com/?test=`\ `got('https://example.com/?test')` → `https://example.com/?test` - To use streams, call `got.stream(url, options)`. #### Breaking changes - The `json` option is not a `boolean`, it's an `object`. It will be stringified and used as a body. - The `form` option is an `object` and will be used as `application/x-www-form-urlencoded` body. - All headers are converted to lowercase.\ According to [the spec](https://datatracker.ietf.org/doc/html/rfc7230#section-3.2), the headers are case-insensitive. - No `oauth` / `hawk` / `aws` / `httpSignature` option.\ To sign requests, you need to create a [custom instance](../examples/advanced-creation.js). - No `agentClass` / `agentOptions` / `pool` option. - No `forever` option.\ You need to pass an agent with `keepAlive` option set to `true`. - No `proxy` option. You need to [pass a custom agent](../tips.md#proxying). - No `auth` option.\ You need to use [`username`](../2-options.md#username) / [`password`](../2-options.md#password) instead or set the `authorization` header manually. - No `baseUrl` option.\ Instead, there is [`prefixUrl`](../2-options.md#prefixurl) which appends a trailing slash if not present. - No `removeRefererHeader` option.\ You can remove the `referer` header in a [`beforeRequest` hook](../9-hooks.md#beforerequest). - No `followAllRedirects` option. - [`copyPipedHeaders`](../2-options.md#copypipedheaders) defaults to `false`.\ Piped request headers are no longer copied automatically. Opt in with `copyPipedHeaders: true` for proxy scenarios. - With `copyPipedHeaders: true`, explicitly set headers win over piped headers.\ Piped headers only fill headers that were not explicitly set. Hooks are very powerful. [Read more](../9-hooks.md) to see what else you achieve using hooks. #### More about streams Let's take a quick look at another example from Request's readme: ```js http.createServer((serverRequest, serverResponse) => { if (serverRequest.url === '/doodle.png') { serverRequest.pipe(request('https://example.com/doodle.png')).pipe(serverResponse); } }); ``` Request can proxy headers with the stream. Got can do that too, but it is opt-in: ```js import {pipeline as streamPipeline} from 'node:stream/promises'; import got from 'got'; const server = http.createServer(async (serverRequest, serverResponse) => { if (serverRequest.url === '/doodle.png') { await streamPipeline( serverRequest, got.stream('https://example.com/doodle.png', {copyPipedHeaders: true}), serverResponse ); } }); server.listen(8080); ``` In terms of stream usage, nothing has really changed, but header proxying is opt-in via `copyPipedHeaders: true`. #### Convenience methods - If you were using `request.get`, `request.post`, and so on - you can do the same with Got. - The `request.defaults({…})` method has been renamed. You can do the same with `got.extend({…})`. - There is no `request.cookie()` nor `request.jar()`. You have to use `tough-cookie` directly. #### You're good to go! Well, you have already come this far :tada:\ Take a look at the [documentation](../../readme.md#documentation). It's worth the time to read it.\ There are [some great tips](../tips.md). If something is unclear or doesn't work as it should, don't hesitate to [open an issue](https://github.com/sindresorhus/got/issues/new/choose). --- ## File: documentation/1-promise.md [> Back to homepage](../readme.md#documentation) ## Promise API Source code: [`source/as-promise/index.ts`](../source/as-promise/index.ts) The main Got function returns a [`Promise`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise).\ Request aborting is supported via the [`signal` option](2-options.md#signal) and [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController). ### `got(url: string | URL, options?: [OptionsInit](typescript.md#optionsinit), defaults?: [Options](2-options.md))` **Returns: `Promise<[Response](response.md)>`** The most common way is to pass the URL as the first argument, then the options as the second. ```js import got from 'got'; const {headers} = await got( 'https://httpbin.org/anything', { headers: { foo: 'bar' } } ).json(); ``` ### `promise.json()` **Returns: `Promise`** A shortcut method that gives a Promise returning a JSON object. It is semantically the same as setting [`options.resolveBodyOnly`](2-options.md#resolvebodyonly) to `true` and [`options.responseType`](2-options.md#responsetype) to `'json'`. ### `promise.buffer()` **Returns: `Promise`** A shortcut method that gives a Promise returning a [Uint8Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array). It is semantically the same as setting [`options.resolveBodyOnly`](2-options.md#resolvebodyonly) to `true` and [`options.responseType`](2-options.md#responsetype) to `'buffer'`. ### `promise.text()` **Returns: `Promise`** A shortcut method that gives a Promise returning a string. It is semantically the same as setting [`options.resolveBodyOnly`](2-options.md#resolvebodyonly) to `true` and [`options.responseType`](2-options.md#responsetype) to `'text'`. ### `promise.on(event, handler)` The events are the same as in [Stream API](3-streams.md#events). ### `promise.once(event, handler)` Registers a one-time listener for events from [Stream API](3-streams.md#events). ### `promise.off(event, handler)` Removes listener registered with [`promise.on`](1-promise.md#promiseonevent-handler). ```js import {createReadStream} from 'node:fs'; import got from 'got'; const ongoingRequestPromise = got.post(uploadUrl, { body: createReadStream('sample.txt') }); const eventListener = (progress: Progress) => { console.log(progress); }; ongoingRequestPromise.on('uploadProgress', eventListener); setTimeout(() => { ongoingRequestPromise.off('uploadProgress', eventListener); }, 500); await ongoingRequestPromise; ``` --- ## File: documentation/2-options.md [> Back to homepage](../readme.md#documentation) ## Options Source code: [`source/core/options.ts`](../source/core/options.ts) Like `fetch` stores the options in a `Request` instance, Got does so in `Options`.\ It is made of getters and setters that provide fast option normalization and validation. **By default, Got will retry on failure. To disable this option, set [`options.retry`](7-retry.md) to `{limit: 0}`.** #### Merge behavior explained When an option is already set, setting it again replaces it with a deep clone by default.\ Otherwise the merge behavior is documented in the corresponding section for the option. #### How to store options The `Options` class is useful for storing and validating configuration for Got instances. The constructor - `new Options(url, options, defaults)` - takes the same arguments as the `got` function. To use an `Options` instance, create an extended Got instance: ```js import got, {Options} from 'got'; const options = new Options({ prefixUrl: 'https://httpbin.org', headers: { foo: 'foo' } }); options.headers.foo = 'bar'; // Use got.extend() to create an instance with the Options const instance = got.extend(options); const {headers} = await instance('anything').json(); console.log(headers.foo); //=> 'bar' ``` For most use cases, plain objects are simpler and more convenient: ```js import got from 'got'; const options = { prefixUrl: 'https://httpbin.org', headers: { foo: 'foo' } }; options.headers.foo = 'bar'; // Plain objects can be passed directly as the second argument const {headers} = await got('anything', options).json(); console.log(headers.foo); //=> 'bar' ``` Note that the `Options` constructor throws immediately when an invalid option is provided, such as a non-existing option or a typo. With plain objects, validation only happens when the request is made. For TypeScript users, `got` exports a dedicated type called `OptionsInit`.\ It is a plain object that can store the same properties as `Options`. The `Options` class is useful for storing the base configuration of a custom Got client, especially when you want early validation of options. #### Resetting options Unlike Got 11, explicitly specifying `undefined` no longer keeps the parent value.\ In order to keep the parent value, you must not set an option to `undefined`.\ Doing so will reset those values: ```js instance(…, {searchParams: undefined}); instance(…, {cookieJar: undefined}); instance(…, {responseType: undefined}); instance(…, {prefixUrl: ''}); instance(…, {agent: {http: undefined, https: undefined, http2: undefined}}); instance(…, {context: {token: undefined, …}}); instance(…, {https: {rejectUnauthorized: undefined, …}}); instance(…, {cacheOptions: {immutableMinTimeToLive: undefined, …}}); instance(…, {headers: {'user-agent': undefined, …}}); instance(…, {timeout: {request: undefined, …}}); ``` In order to reset `hooks`, `retry` and `pagination`, another Got instance must be created: ```js const defaults = new Options(); const secondInstance = instance.extend({mutableDefaults: true}); secondInstance.defaults.options.hooks = defaults.hooks; secondInstance.defaults.options.retry = defaults.retry; secondInstance.defaults.options.pagination = defaults.pagination; ``` ### `url` **Type: `string | [URL](https://nodejs.org/api/url.html#url_the_whatwg_url_api)`** The URL to request. Usually the `url` represents a [WHATWG URL](https://url.spec.whatwg.org/#url-class). Pass it as the first argument to `got(url, options)`. Passing `url` in an options object is not supported. ```js import got from 'got'; // This: await got('https://httpbin.org/anything'); // is semantically the same as this: await got(new URL('https://httpbin.org/anything')); ``` > [!NOTE] > Throws if no protocol specified. > [!NOTE] > If `url` is a string, then the `query` string will **not** be parsed as search params.\ > This is in accordance to [the specification](https://datatracker.ietf.org/doc/html/rfc7230#section-2.7).\ > If you want to pass search params instead, use the `searchParams` option below. ```js import got from 'got'; await got('https://httpbin.org/anything?query=a b'); //=> ?query=a%20b await got('https://httpbin.org/anything', {searchParams: {query: 'a b'}}); //=> ?query=a+b // The query string is overridden by `searchParams` await got('https://httpbin.org/anything?query=a b', {searchParams: {query: 'a b'}}); //=> ?query=a+b ``` > [!NOTE] > Leading slashes are disallowed to enforce consistency and avoid confusion.\ > For example, when the prefix URL is `https://example.com/foo` and the input is `/bar`, there's ambiguity whether the resulting URL would become `https://example.com/foo/bar` or `https://example.com/bar`. The latter is used by browsers. ### `searchParams` **Type: `string | [URLSearchParams](https://nodejs.org/api/url.html#url_class_urlsearchparams) | object<string, [Primitive](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html)>`** [WHATWG URL Search Params](https://url.spec.whatwg.org/#interface-urlsearchparams) to be added to the request URL. ```js import got from 'got'; const response = await got('https://httpbin.org/anything', { searchParams: { hello: 'world', foo: 123 } }).json(); console.log(response.args); //=> {hello: 'world', foo: 123} ``` If you need to pass an array, you can do it using a `URLSearchParams` instance: ```js import got from 'got'; const searchParams = new URLSearchParams([['key', 'a'], ['key', 'b']]); await got('https://httpbin.org/anything', {searchParams}); console.log(searchParams.toString()); //=> 'key=a&key=b' ``` > [!NOTE] > This will override the `query` string in `url`. > [!NOTE] > - `null` values are not stringified, an empty string is used instead. > - `undefined` values will clear the original keys. #### **Merge behavior:** > - Overrides existing properties. ### `prefixUrl` **Type: `string`**\ **Default: `''`** The string to be prepended to relative string `url` input. The prefix can be any valid URL, either relative or [absolute](https://url.spec.whatwg.org/#absolute-url-string). A trailing slash `/` is optional - one will be added automatically. ```js import got from 'got'; // This: const instance = got.extend({prefixUrl: 'https://httpbin.org'}); await instance('anything'); // is semantically the same as this: await got('https://httpbin.org/anything'); ``` > [!NOTE] > Changing `prefixUrl` also updates the `url` option if set. > [!NOTE] > Absolute string URLs and `URL` instances bypass `prefixUrl` by default. Other instance defaults, including `headers`, still apply. If those URLs may come from untrusted input, set [`allowAbsoluteUrls`](#allowabsoluteurls) to `false`. > [!NOTE] > Got cannot know which custom headers are sensitive. If you use headers like `x-api-key`, only pass trusted URLs or use `allowAbsoluteUrls: false`. ### `allowAbsoluteUrls` **Type: `boolean`**\ **Default: `true`** Allow absolute URLs to bypass `prefixUrl`. When set to `false` with `prefixUrl`, passing an absolute URL will throw. This also rejects scheme-relative URL strings like `//example.com/path` in retry and pagination URL overrides. Use this when untrusted URL input must stay on the same origin as the configured `prefixUrl`. This is not a path sandbox: relative paths like `../other` still follow standard URL resolution on the same origin. ```js import got from 'got'; const client = got.extend({ prefixUrl: 'https://api.example.com', allowAbsoluteUrls: false, headers: { 'x-api-key': process.env.API_KEY } }); await client('users/1'); // Requests https://api.example.com/users/1 await client('https://attacker.example'); // Throws ``` Set `prefixUrl` to an empty string for a request that intentionally needs an absolute URL: ```js await client('https://trusted.example', {prefixUrl: ''}); ``` > [!NOTE] > This guards the `url` you pass. It does not block cross-origin redirects issued by the server, though inherited sensitive headers are still stripped when a redirect changes origin. > [!NOTE] > The check is defeated if the same hook or `pagination.paginate(…)` return also sets `prefixUrl` or `allowAbsoluteUrls`. Do not populate those options from untrusted data. ### `signal` **Type: [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal)** You can abort the `request` using [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController). ```js import got from 'got'; const abortController = new AbortController(); const request = got('https://httpbin.org/anything', { signal: abortController.signal }); setTimeout(() => { abortController.abort(); }, 100); ``` ### `method` **Type: `string`**\ **Default: `GET`** The [HTTP method](https://httpwg.org/specs/rfc9110.html#methods) used to make the request.\ Common methods include: `GET`, `HEAD`, `POST`, `PUT`, `DELETE`. Got also supports `QUERY`, which is defined in [RFC 10008](https://www.rfc-editor.org/rfc/rfc10008.html). ```js import got from 'got'; const {method} = await got('https://httpbin.org/anything', { method: 'POST' }).json(); console.log(method); // => 'POST' ``` ### `headers` **Type: `object`**\ **Default: `{}`** The [HTTP headers](https://datatracker.ietf.org/doc/html/rfc7231#section-8.3) to be sent. Headers set to `undefined` will be omitted. ```js import got from 'got'; const {headers} = await got.post('https://httpbin.org/anything', { headers: { hello: 'world' } }).json(); console.log(headers); // => {hello: 'world'} ``` #### **Merge behavior:** > - Overrides existing properties. ### `body` **Type: `string | Uint8Array | TypedArray | stream.Readable | Generator | AsyncGenerator | Iterable | AsyncIterable | FormData`** The payload to send. For `string`, `Uint8Array`, and `TypedArray` types, the `content-length` header is automatically set if the `content-length` and `transfer-encoding` headers are missing. **The `content-length` header is not automatically set when `body` is an instance of [`fs.createReadStream()`](https://nodejs.org/api/fs.html#fs_fs_createreadstream_path_options).** To set `content-length` for file streams, you need to manually provide it using `fs.promises.stat()`: ```js import fs from 'node:fs'; import fsPromises from 'node:fs/promises'; import got from 'got'; const filePath = 'path/to/file'; const fileStats = await fsPromises.stat(filePath); const fileStream = fs.createReadStream(filePath); await got.post('https://httpbin.org/anything', { body: fileStream, headers: { 'content-length': fileStats.size.toString() } }); ``` ```js import got from 'got'; const {data} = await got.post('https://httpbin.org/anything', { body: 'Hello, world!' }).json(); console.log(data); //=> 'Hello, world!' ``` You can also use typed arrays (Uint8Array, Uint16Array, etc.) as request body: ```js import got from 'got'; const uint8Body = new Uint8Array([104, 101, 108, 108, 111]); // 'hello' in ASCII const {data} = await got.post('https://httpbin.org/anything', { body: uint8Body }).json(); console.log(data); //=> 'hello' ``` You can use `Iterable` and `AsyncIterable` objects as request body, including Web [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream): ```js import got from 'got'; // Using an async generator async function* generateData() { yield 'Hello, '; yield 'world!'; } await got.post('https://httpbin.org/anything', { body: generateData() }); ``` You can use [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) objects as request body: ```js import got from 'got'; const form = new FormData(); form.set('greeting', 'Hello, world!'); const data = await got.post('https://httpbin.org/post', { body: form }).json(); console.log(data.form.greeting); //=> 'Hello, world!' ``` > [!NOTE] > If `body` is specified, then the `json` or `form` option cannot be used. > [!NOTE] > If you use this option, `got.stream()` will be read-only. > [!NOTE] > Passing `body` with `GET` will throw unless the [`allowGetBody` option](#allowgetbody) is set to `true`. > [!NOTE] > This option is not enumerable and will not be merged with the instance defaults. ### `json` **Type: JSON-serializable values** JSON **request** body. If set, the `content-type` header defaults to `application/json`. > [!IMPORTANT] > This option only affects the **request body** you send to the server. To parse the **response** as JSON, you must either call `.json()` on the promise or set [`responseType: 'json'`](#responsetype) in the options. ```js import got from 'got'; const {data} = await got.post('https://httpbin.org/anything', { json: { hello: 'world' } }).json(); console.log(data); //=> `{hello: 'world'}` ``` ### `form` **Type: `object<string, [Primitive](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html)>`** The form body is converted to a query string using `(new URLSearchParams(form)).toString()`. If set, the `content-type` header defaults to [`application/x-www-form-urlencoded`](https://url.spec.whatwg.org/#application/x-www-form-urlencoded). ```js import got from 'got'; const {data} = await got.post('https://httpbin.org/anything', { form: { hello: 'world' } }).json(); console.log(data); //=> 'hello=world' ``` ### `parseJson` **Type: `(text: string) => unknown`**\ **Default: `(text: string) => JSON.parse(text)`** The function used to parse JSON responses. ```js import got from 'got'; import Bourne from '@hapi/bourne'; // Preventing prototype pollution by using Bourne const parsed = await got('https://example.com', { parseJson: text => Bourne.parse(text) }).json(); console.log(parsed); ``` ### `stringifyJson` **Type: `(object: unknown) => string`**\ **Default: `(object: unknown) => JSON.stringify(object)`** The function used to stringify the body of JSON requests. **Example: ignore all properties starting with an underscore** ```js import got from 'got'; await got.post('https://example.com', { stringifyJson: object => JSON.stringify(object, (key, value) => { if (key.startsWith('_')) { return; } return value; }), json: { some: 'payload', _ignoreMe: 1234 } }); ``` **Example: all numbers as strings** ```js import got from 'got'; await got.post('https://example.com', { stringifyJson: object => JSON.stringify(object, (key, value) => { if (typeof value === 'number') { return value.toString(); } return value; }), json: { some: 'payload', number: 1 } }); ``` ### `allowGetBody` **Type: `boolean`**\ **Default: `false`** Set this to `true` to allow sending body for the `GET` method. > [!NOTE] > This option is only meant to interact with non-compliant servers when you have no other choice. > [!NOTE] > The [RFC 7231](https://tools.ietf.org/html/rfc7231#section-4.3.1) doesn't specify any particular behavior for the GET method having a payload, therefore it's considered an [**anti-pattern**](https://en.wikipedia.org/wiki/Anti-pattern). ### `copyPipedHeaders` **Type: `boolean`**\ **Default: `false`** Automatically copy headers from piped streams. When piping a request into a Got stream (e.g., `request.pipe(got.stream(url))`), this controls whether headers from the source stream are automatically merged into the Got request headers. **Note:** Explicitly set headers take precedence over piped headers. Piped headers are only copied when a header is not already explicitly set. Useful for proxy scenarios when explicitly enabled. Got automatically omits `host`, hop-by-hop headers, and headers nominated by `Connection`, but you may still want to filter out app-specific sensitive headers like `Authorization`, `Cookie`, etc. **Example: Opt in to automatic header copying for proxy scenarios** ```js import got from 'got'; import {pipeline} from 'node:stream/promises'; server.get('/proxy', async (request, response) => { const gotStream = got.stream('https://example.com', { copyPipedHeaders: true, // Explicit headers win over piped headers headers: { host: 'example.com', } }); await pipeline(request, gotStream, response); }); ``` **Example: Keep it disabled and manually copy only safe headers** ```js import got from 'got'; import {pipeline} from 'node:stream/promises'; server.get('/proxy', async (request, response) => { const gotStream = got.stream('https://example.com', { headers: { 'user-agent': request.headers['user-agent'], 'accept': request.headers['accept'], // Explicitly NOT copying host, connection, authorization, etc. } }); await pipeline(request, gotStream, response); }); ``` ### `timeout` **Type: `object`** See the [Timeout API](6-timeout.md). #### **Merge behavior:** > - Overrides existing properties. ### `retry` **Type: `object`** See the [Retry API](7-retry.md). #### **Merge behavior:** > - Overrides existing properties. ### `hooks` **Type: `object`** See the [Hooks API](9-hooks.md). #### **Merge behavior:** > - Merges arrays via `[...hooksArray, ...next]` ### `encoding` **Type: `string`**\ **Default: `'utf8'`** [Encoding](https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings) to be used on [`setEncoding`](https://nodejs.org/api/stream.html#stream_readable_setencoding_encoding) of the response data. To get a [`Uint8Array`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array), you need to set `responseType` to `'buffer'` instead. Don't set this option to `null`. ```js import got from 'got'; const response = await got('https://httpbin.org/anything', { encoding: 'base64' }).text(); console.log(response); //=> base64 string ``` #### **Note:** > - This option does not affect streams! Instead, do: ```js import got from 'got'; const stream = got.stream('https://httpbin.org/anything'); stream.setEncoding('base64'); stream.on('data', console.log); ``` ### `responseType` **Type: `'text' | 'json' | 'buffer'`**\ **Default: `'text'`** The parsing method. The promise also has `.text()`, `.json()` and `.buffer()` methods which return another Got promise for the parsed body.\ It's like setting the options to `{responseType: 'json', resolveBodyOnly: true}` but without affecting the main Got promise. ```js import got from 'got'; const responsePromise = got('https://httpbin.org/anything'); const bufferPromise = responsePromise.buffer(); const jsonPromise = responsePromise.json(); const [response, buffer, json] = await Promise.all([responsePromise, bufferPromise, jsonPromise]); // `response` is an instance of Got Response // `buffer` is an instance of Uint8Array // `json` is an object ``` > [!NOTE] > When using streams, this option is ignored. > [!NOTE] > `'buffer'` will return the raw body bytes as a `Uint8Array`. Any modifications will also alter the result of `.text()` and `.json()`. Before overwriting it, please copy it first via `new Uint8Array(buffer)`.\ > See https://github.com/nodejs/node/issues/27080 ### `resolveBodyOnly` **Type: `boolean`**\ **Default: `false`** If `true`, the promise will return the [Response body](3-streams.md#response-2) instead of the [Response object](3-streams.md#response-2). ```js import got from 'got'; const url = 'https://httpbin.org/anything'; // This: const body = await got(url).json(); // is semantically the same as this: const body = await got(url, {responseType: 'json', resolveBodyOnly: true}); ``` ### `context` **Type: `object`**\ **Default: `{}`** **Note:** > - Non-enumerable properties inside are **not** merged. Contains user data. It's very useful for storing auth tokens: ```js import got from 'got'; const instance = got.extend({ hooks: { beforeRequest: [ options => { if (typeof options.context.token !== 'string') { throw new Error('Token required'); } options.headers.token = options.context.token; } ] } }); const context = { token: 'secret' }; const {headers} = await instance('https://httpbin.org/headers', {context}).json(); console.log(headers); //=> {token: 'secret', …} ``` This option is enumerable. In order to define non-enumerable properties inside, do the following: ```js import got from 'got'; const context = {}; Object.defineProperties(context, { token: { value: 'secret', enumerable: false, configurable: true, writable: true } }); const instance = got.extend({context}); console.log(instance.defaults.options.context); //=> {} ``` #### **Merge behavior:** > - Overrides existing properties. ### `cookieJar` **Type: `object | [tough.cookieJar](https://github.com/salesforce/tough-cookie#cookiejar)`** #### **Note:** > - Setting this option will result in the `cookie` header being overwritten. Cookie support. Handles parsing and storing automatically. ```js import got from 'got'; import {CookieJar} from 'tough-cookie'; const cookieJar = new CookieJar(); await cookieJar.setCookie('foo=bar', 'https://example.com'); await got('https://example.com', {cookieJar}); ``` #### `cookieJar.setCookie` **Type: `(rawCookie: string, url: string) => void | Promise`** See [ToughCookie API](https://github.com/salesforce/tough-cookie#setcookiecookieorstring-currenturl-options-cberrcookie) for more information. #### `cookieJar.getCookieString` **Type: `(currentUrl: string) => string | Promise`** See [ToughCookie API](https://github.com/salesforce/tough-cookie#getcookiestring) for more information. ### `ignoreInvalidCookies` **Type: `boolean`**\ **Default: `false`** Ignore invalid cookies instead of throwing an error.\ Only useful when the `cookieJar` option has been set. #### **Note:** > - This is not recommended! Use at your own risk. ### `followRedirect` **Type: `boolean | (response: PlainResponse) => boolean`**\ **Default: `true`** Whether redirect responses should be followed automatically. Optionally, pass a function to dynamically decide based on the response object. #### **Note:** > - If a `303` is sent by the server in response to any request type (POST, DELETE, etc.), Got will request the resource pointed to in the location header via GET.\ > This is in accordance with the [specification](https://tools.ietf.org/html/rfc7231#section-6.4.4). You can optionally turn on this behavior also for other redirect codes - see [`methodRewriting`](#methodrewriting). > - On cross-origin redirects, Got strips `host`, `cookie`, `cookie2`, `authorization`, and `proxy-authorization`, as well as any credentials embedded in the URL. > - `307` and `308` redirects preserve the request method and replayable body, even across origins, as required by the specification. `QUERY` requests also preserve replayable bodies on `301` and `302` redirects because `QUERY` is safe and idempotent. Got fails instead of following when the body cannot be replayed. > - Other cross-origin redirects can drop the request body and request body headers to avoid forwarding payloads to another origin. > - When a redirect rewrites the request to `GET`, Got also strips request body headers. > - Use [`hooks.beforeRedirect`](9-hooks.md#beforeredirect) for app-specific sensitive headers. ```js import got from 'got'; const instance = got.extend({followRedirect: false}); const response = await instance('http://google.com'); console.log(response.headers.location); //=> 'https://google.com' ``` ### `maxRedirects` **Type: `number`**\ **Default: `10`** If exceeded, the request will be aborted and a [`MaxRedirectsError`](8-errors.md#maxredirectserror) will be thrown. ```js import got from 'got'; const instance = got.extend({maxRedirects: 3}); try { await instance('https://nghttp2.org/httpbin/absolute-redirect/5'); } catch (error) { //=> 'Redirected 3 times. Aborting.' console.log(error.message); } ``` ### `decompress` **Type: `boolean`**\ **Default: `true`** Decompress the response automatically. This will set the `accept-encoding` header to `gzip, deflate, br` (and `zstd` on Node.js >= 22.15.0). If disabled, a compressed response is returned as a `Uint8Array`. This may be useful if you want to handle decompression yourself. > [!NOTE] > Zstandard (`zstd`) compression support is available on Node.js >= 22.15.0 and will be automatically enabled when available. ```js import got from 'got'; const response = await got('https://google.com'); console.log(response.headers['content-encoding']); //=> 'gzip' ``` ### `strictContentLength` **Type: `boolean`**\ **Default: `true`** Throw an error if the server response's `content-length` header value doesn't match the number of bytes received. This is useful for detecting truncated responses and follows RFC 9112 requirements for message completeness. > [!NOTE] > - Responses without a `content-length` header are not validated. > - When enabled and validation fails, a [`ReadError`](8-errors.md#readerror) with code `ERR_HTTP_CONTENT_LENGTH_MISMATCH` will be thrown. ### `dnsLookup` **Type: `Function`**\ **Default: [`dns.lookup`](https://nodejs.org/api/dns.html#dns_dns_lookup_hostname_options_callback)** Custom DNS resolution logic. The function signature is the same as `dns.lookup`. ### `dnsCache` **Type: `{lookup: Function; clear?: Function} | boolean`** A DNS cache instance used for making DNS lookups.\ Useful when making lots of requests to different public hostnames. Set to `true` to use Got's shared DNS cache. When using `got.extend()`, set to `false` to opt out of a DNS cache configured by the parent instance. **Note:** > - This should stay disabled when making requests to internal hostnames such as localhost, database.local etc. > - Got's built-in DNS cache uses `dns.resolve4(…)` and `dns.resolve6(…)` under the hood and falls back to `dns.lookup(…)` when no DNS records are found, which may lead to additional delay. > - Because Got's built-in DNS cache resolves A and AAAA records separately, it cannot preserve OS-specific `verbatim` address ordering from `dns.lookup(…)`. > - If present, `clear(hostname?)` can be called by user code to clear cached entries. ### `dnsLookupIpVersion` **Type: `4 | 6`**\ **Default: `undefined`** The IP version to use. Specifying `undefined` will use the default configuration. ### `request` **Type: `Function<[ClientRequest](https://nodejs.org/api/http.html#http_class_http_clientrequest) | [IncomingMessage](https://nodejs.org/api/http.html#http_class_http_incomingmessage) | undefined> | AsyncFunction<[ClientRequest](https://nodejs.org/api/http.html#http_class_http_clientrequest) | [IncomingMessage](https://nodejs.org/api/http.html#http_class_http_incomingmessage) | undefined>`**\ **Default: Got's built-in HTTP/1.1 or HTTP/2 request implementation** Custom request function. Returning `undefined` (or resolving to `undefined`) will fall back to Got's native request implementation. ### `cache` **Type: `object | false`**\ **Default: `false`** [Cache adapter instance](cache.md) for storing cached response data. ### `cacheOptions` **Type: `object`**\ **Default: `{}`** [Cache options](https://github.com/kornelski/http-cache-semantics#constructor-options) used for the specified request. ### `http2` **Type: `boolean`**\ **Default: `false`** If `true`, Got will use its built-in HTTP/2 client when ALPN selects HTTP/2. **Note:** > - ALPN negotiation will take place in order to determine if the server actually supports HTTP/2. If it doesn't, HTTP/1.1 will be used. When a custom `agent.https` instance is set, Got uses that native HTTPS agent directly and skips HTTP/2 negotiation. **Note:** > - If the `request` option returns a request or response, it controls the transport and Got's HTTP/2 client is bypassed. Return `undefined` to fall back to Got's built-in transport. **Note:** > - There is no direct [`h2c` Upgrade](https://datatracker.ietf.org/doc/html/rfc9113#section-11.2) support. However, you can provide a `h2session` option in a `beforeRequest` hook. See [an example](examples/h2c.js). ```js import got from 'got'; const {statusCode} = await got( 'https://httpbin.org/anything', { http2: true } ); console.log(statusCode); //=> 200 ``` ### `agent` **Type: `object`**\ **Default: `{}`** An object with `http`, `https` and `http2` properties. Got will automatically resolve the protocol and use the corresponding agent. HTTP/2 uses Got's internal session pool by default. Set `agent.http2` to `false` to disable HTTP/2 session pooling for the request. `agent.http2` is only a pooling opt-out flag; custom HTTP/2 agents are not part of the public API. When `http2` is enabled, a custom `agent.https` instance makes Got use the native HTTP/1.1 request path because Got's built-in HTTP/2 session pool does not support custom HTTPS agents. ```js { http: http.globalAgent, https: https.globalAgent } ``` ### `throwHttpErrors` **Type: `boolean`**\ **Default: `true`** If `true`, it will [throw](8-errors.md#httperror) when the status code is not `2xx` / `3xx`. If this is disabled, requests that encounter an error status code will be resolved with the response instead of throwing. This may be useful if you are checking for resource availability and are expecting error responses. ### `username` **Type: `string`**\ **Default: `''`** The `username` used for [Basic authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication). ### `password` **Type: `string`**\ **Default: `''`** The `password` used for [Basic authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication). ### `localAddress` **Type: `string | undefined`**\ **Default: `undefined`** The local IP address used to make the request. ### `createConnection` **Type: `Function | undefined`**\ **Default: `undefined`** The function used to retrieve a `net.Socket` instance when the `agent` option is not used. ### `https` **Type: `object`** See [Advanced HTTPS API](5-https.md). ### `pagination` **Type: `object`** See [Pagination API](4-pagination.md). ### `setHost` **Type: `boolean`**\ **Default: `true`** Specifies whether or not to automatically add the `Host` header. ### `maxHeaderSize` **Type: `number | undefined`**\ **Default: `undefined`** Optionally overrides the value of [`--max-http-header-size`](https://nodejs.org/api/cli.html#cli_max_http_header_size_size) (default 16KB: `16384`). ### `methodRewriting` **Type: `boolean`**\ **Default: `false`** Specifies if the HTTP request method should be [rewritten as `GET`](https://tools.ietf.org/html/rfc7231#section-6.4) on redirects. As the [specification](https://tools.ietf.org/html/rfc7231#section-6.4) prefers to rewrite the HTTP method only on `303` responses, this is Got's default behavior. Cross-origin `301` and `302` redirects also rewrite `POST` requests to `GET` by default to avoid forwarding request bodies to another origin. Setting `methodRewriting` to `true` will also rewrite same-origin `301` and `302` responses, as allowed by the spec. This is the behavior followed by `curl` and browsers. **Note:** > - Got never performs method rewriting on `307` and `308` responses, as this is [explicitly prohibited by the specification](https://www.rfc-editor.org/rfc/rfc7231#section-6.4.7). ### `enableUnixSockets` **Type: `boolean`**\ **Default: `false`** When enabled, requests can also be sent via [UNIX Domain Sockets](https://serverfault.com/questions/124517/what-is-the-difference-between-unix-sockets-and-tcp-ip-sockets). > **Warning** > Make sure you do your own URL sanitizing if you accept untrusted user input for the URL. Use the following URL scheme: `PROTOCOL://unix:SOCKET:PATH` - `PROTOCOL` - `http` or `https` - `SOCKET` - Absolute path to a UNIX domain socket, for example: `/var/run/docker.sock` - `PATH` - Request path, for example: `/v2/keys` ```js import got from 'got'; await got('http://unix:/var/run/docker.sock:/containers/json', {enableUnixSockets: true}); // Or without protocol (HTTP by default) await got('unix:/var/run/docker.sock:/containers/json', {enableUnixSockets: true}); // Enable Unix sockets for the whole instance. const gotWithUnixSockets = got.extend({enableUnixSockets: true}); await gotWithUnixSockets('http://unix:/var/run/docker.sock:/containers/json'); ``` ## Methods ### `options.merge(other: Options | OptionsInit)` Merges `other` into the current instance. If you look at the [source code](../source/core/options.ts), you will notice that options track internal merge state.\ Setters work a bit differently while merge is in progress. ### `options.toJSON()` Returns a new plain object that can be stored as [JSON](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#tojson_behavior). ### `options.createNativeRequestOptions()` Creates a new object for native Node.js HTTP request options. In other words, this translates Got options into Node.js options. **Note:** > - Some other stuff, such as timeouts, is handled internally by Got. ### `options.getRequestFunction()` Returns a [`http.request`-like](https://nodejs.org/api/http.html#http_http_request_url_options_callback) function used to make the request. ### `options.freeze()` Makes the entire `Options` instance read-only. --- ## File: documentation/3-streams.md [> 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. --- ## File: documentation/4-pagination.md [> Back to homepage](../readme.md#documentation) ## Pagination API Source code: [`source/create.ts`](../source/create.ts) ### How does the `Link` header work? The [RFC5988](https://datatracker.ietf.org/doc/html/rfc5988#section-5) defines how the `Link` header looks like. When the response has been processed, Got looks for [the reference of the `next` relation](https://datatracker.ietf.org/doc/html/rfc5988#section-6.2.2).\ This way Got knows the URL it should visit afterwards. The header can look like this: ```text Link: ; rel="next", ; rel="last" ``` By default, Got looks only at the `next` relation. To use [other relations](https://datatracker.ietf.org/doc/html/rfc5988#section-6.2.2), you need to customize the `paginate` function below. ### `got.paginate(url, options?)` ### `got.paginate.each(url, options?)` Returns an [async iterator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of). This is memory efficient, as the logic is executed immediately when new data comes in. ```js import got from 'got'; const countLimit = 10; const pagination = got.paginate( 'https://api.github.com/repos/sindresorhus/got/commits', { pagination: {countLimit} } ); console.log(`Printing latest ${countLimit} Got commits (newest to oldest):`); for await (const commitData of pagination) { console.log(commitData.commit.message); } ``` ### `got.paginate.all(url, options?)` **Note:** > - Querying a large dataset significantly increases memory usage. Returns a Promise for an array of all results. ```js import got from 'got'; const countLimit = 10; const results = await got.paginate.all('https://api.github.com/repos/sindresorhus/got/commits', { pagination: {countLimit} }); console.log(`Printing latest ${countLimit} Got commits (newest to oldest):`); console.log(results); ``` ### `pagination` **Type: `object`**\ **Default:** ```js { transform: (response: Response) => { if (response.request.options.responseType === 'json') { return response.body; } return JSON.parse(response.body as string); }, paginate: ({response}) => { const rawLinkHeader = response.headers.link; if (typeof rawLinkHeader !== 'string' || rawLinkHeader.trim() === '') { return false; } const parsed = parseLinkHeader(rawLinkHeader); const next = parsed.find(entry => entry.parameters.rel === 'next' || entry.parameters.rel === '"next"'); if (next) { return { url: next.reference }; } return false; }, filter: () => true, shouldContinue: () => true, countLimit: Number.POSITIVE_INFINITY, backoff: 0, requestLimit: 10_000, stackAllItems: false } ``` This option represents the `pagination` object. #### `transform` **Type: `Function`**\ **Default: `response => JSON.parse(response.body)`** A function that transforms [`Response`](3-streams.md#response-2) into an array of items.\ This is where you should do the parsing. #### `paginate` **Type: `Function`**\ **Default: `Link` header logic** The function takes an object with the following properties: - `response` - The current response object, - `currentItems` - Items from the current response, - `allItems` - An empty array, unless `stackAllItems` is `true`, otherwise it contains all emitted items. It should return an object representing Got options pointing to the next page. If there is no next page, `false` should be returned instead. The options are merged automatically with the previous request.\ Therefore the options returned by `pagination.paginate(…)` must reflect changes only. **Note:** > - The `url` option (if set) accepts a string or [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL) instance. Relative strings resolve against the current request URL. After a cross-origin redirect, that means the final redirected URL, not the original `prefixUrl`. > - When pagination navigates to a different origin, Got strips inherited sensitive headers such as `authorization`, `cookie`, and `proxy-authorization`. If you trust the next-page URL and want to forward a sensitive header, return it explicitly from `pagination.paginate(…)`. #### `filter` **Type: `Function`**\ **Default: `({item, currentItems, allItems}) => true`** Whether the item should be emitted or not. #### `shouldContinue` **Type: `Function`**\ **Default: `({item, currentItems, allItems}) => true`** **Note:** > - This function executes only when `filter` returns `true`. For example, if you need to stop before emitting an entry with some flag, you should use `({item}) => !item.flag`. If you want to stop after emitting the entry, you should use `({item, allItems}) => allItems.some(item => item.flag)` instead. #### `countLimit` **Type: `number`**\ **Default: `Number.POSITIVE_INFINITY`** The maximum amount of items that should be emitted. #### `backoff` **Type: `number`**\ **Default: `0`** Milliseconds to wait before the next request is triggered. #### `requestLimit` **Type: `number`**\ **Default: `10000`** The maximum amount of request that should be triggered. **Note:** > - [Retries on failure](7-retry.md) are not counted towards this limit. #### `stackAllItems` **Type: `boolean`**\ **Default: `false`** Defines how `allItems` is managed in `pagination.paginate`, `pagination.filter` and `pagination.shouldContinue`. By default, `allItems` is always an empty array. Setting this to `true` will significantly increase memory usage when working with a large dataset. ### Example In this example we will use `searchParams` instead of `Link` header.\ Just to show how you can customize the `paginate` function. The reason `filter` looks exactly the same like `shouldContinue` is that the latter will tell Got to stop once we reach our timestamp. The `filter` function is needed as well, because in the same response we can get results with different timestamps. ```js import got from 'got'; import Bourne from '@hapi/bourne'; const max = Date.now() - 1000 * 86400 * 7; const iterator = got.paginate('https://api.github.com/repos/sindresorhus/got/commits', { pagination: { paginate: ({response, currentItems}) => { // If there are no more data, finish. if (currentItems.length === 0) { return false; } // Get the current page number. const {searchParams} = response.request.options; const previousPage = Number(searchParams.get('page') ?? 1); // Update the page number by one. return { searchParams: { page: previousPage + 1 } }; }, // Using `Bourne` to prevent prototype pollution. transform: response => Bourne.parse(response.body), filter: ({item}) => { // Check if the commit time exceeds our range. const date = new Date(item.commit.committer.date); const end = date.getTime() - max >= 0; return end; }, shouldContinue: ({item}) => { // Check if the commit time exceeds our range. const date = new Date(item.commit.committer.date); const end = date.getTime() - max >= 0; return end; }, // We want only 50 results. countLimit: 50, // Wait 1s before making another request to prevent API rate limiting. backoff: 1000, // It is a good practice to set an upper limit of how many requests can be made. // This way we can avoid infinite loops. requestLimit: 10, // In this case, we don't need to store all the items we receive. // They are processed immediately. stackAllItems: false } }); console.log('Last 50 commits from now to week ago:'); for await (const item of iterator) { console.log(item.commit.message.split('\n')[0]); } ``` --- ## File: documentation/5-https.md [> Back to homepage](../readme.md#documentation) ## Advanced HTTPS API ### `https` **Type: `object`** This option represents the options used to make HTTPS requests. #### `alpnProtocols` **Type: `string[]`**\ **Default: `['http/1.1']`** Acceptable [ALPN](https://en.wikipedia.org/wiki/Application-Layer_Protocol_Negotiation) protocols. If the `http2` option is `true`, this defaults to `['h2', 'http/1.1']`. #### `rejectUnauthorized` **Type: `boolean`**\ **Default: `true`** If `true`, it will throw on invalid certificates, such as expired or self-signed ones. #### `checkServerIdentity` **Type: `(hostname: string, certificate: DetailedPeerCertificate) => Error | undefined`**\ **Default: `tls.checkServerIdentity`** Custom check of the certificate. Useful for pinning certificates. The function must return `undefined` if the check succeeded.\ If it failed, an `Error` should be returned. **Note:** > - In order to have the function called, the certificate must not be expired, self-signed nor with an untrusted-root. Check [Node.js docs](https://nodejs.org/api/https.html#https_https_request_url_options_callback) for an example. #### `serverName` **Type: `string`**\ **Default: `undefined`** Server name for the [Server Name Indication (SNI)](https://en.wikipedia.org/wiki/Server_Name_Indication) TLS extension. This is useful when requesting to servers that don't have a proper domain name but use a certificate with a known CN/SAN. ```js import got from 'got'; // Request to IP address with specific servername for TLS await got('https://192.168.1.100', { https: { serverName: 'example.com' } }); ``` #### `certificateAuthority` **Type: `string | Uint8Array | string[] | Uint8Array[]`** **Note:** > - The option has been renamed from the [`ca` TLS option](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) for better readability. Overrides trusted [CA](https://en.wikipedia.org/wiki/Certificate_authority) certificates. Defaults to CAs provided by [Mozilla](https://ccadb-public.secure.force.com/mozilla/IncludedCACertificateReport). ```js import got from 'got'; // Single Certificate Authority await got('https://example.com', { https: { certificateAuthority: fs.readFileSync('./my_ca.pem') } }); ``` #### `key` **Type: `string | Uint8Array | string[] | Uint8Array[] | object[]`** Private keys in [PEM format](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail). Multiple keys with different passphrases can be provided as an array of `{pem: , passphrase: }`. **Note:** > - Encrypted keys will be decrypted with `https.passphrase`. #### `passphrase` **Type: `string`** Shared passphrase used for a single private key and/or a PFX. #### `certificate` **Type: `string | Uint8Array | string[] | Uint8Array[]`** **Note:** > - The option has been renamed from the [`cert` TLS option](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) for better readability. [Certificate chains](https://en.wikipedia.org/wiki/X.509#Certificate_chains_and_cross-certification) in [PEM format](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail). One certificate chain should be provided per private key. When providing multiple certificate chains, they do not have to be in the same order as their private keys in `https.key`. #### `pfx` **Type: `string | Uint8Array | string[] | Uint8Array[] | object[]`** [PFX or PKCS12](https://en.wikipedia.org/wiki/PKCS_12) encoded private key and certificate chain. Using `https.pfx` is an alternative to providing `https.key` and `https.certificate` individually. A PFX is usually encrypted, then `https.passphrase` will be used to decrypt it. Multiple PFX can be provided as an array of unencrypted buffers or an array of objects like: ```ts { buffer: string | Uint8Array, passphrase?: string } ``` #### `certificateRevocationLists` **Type: `string | Uint8Array | string[] | Uint8Array[]`** **Note:** > - The option has been renamed from the [`crl` TLS option](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) for better readability. #### `secureOptions` **Type: `number`** Optionally affect the OpenSSL protocol behavior, which is not usually necessary. This should be used carefully if at all! The value is a numeric bitmask of the `SSL_OP_*` options from OpenSSL. For example, to allow connections to legacy servers that do not support secure renegotiation, you can use `crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT`. ```js import crypto from 'node:crypto'; import got from 'got'; // Allow connections to servers with legacy renegotiation await got('https://legacy-server.com', { https: { secureOptions: crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT } }); ``` ### Other HTTPS options [Documentation for the below options.](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) - `ciphers` - `dhparam` - `signatureAlgorithms` (renamed from `sigalgs`) - `minVersion` - `maxVersion` - `honorCipherOrder` - `tlsSessionLifetime` (renamed from `sessionTimeout`) - `ecdhCurve` ### Examples ```js import got from 'got'; // Single key with certificate await got('https://example.com', { https: { key: fs.readFileSync('./client_key.pem'), certificate: fs.readFileSync('./client_cert.pem') } }); // Multiple keys with certificates (out of order) await got('https://example.com', { https: { key: [ fs.readFileSync('./client_key1.pem'), fs.readFileSync('./client_key2.pem') ], certificate: [ fs.readFileSync('./client_cert2.pem'), fs.readFileSync('./client_cert1.pem') ] } }); // Single key with passphrase await got('https://example.com', { https: { key: fs.readFileSync('./client_key.pem'), certificate: fs.readFileSync('./client_cert.pem'), passphrase: 'client_key_passphrase' } }); // Multiple keys with different passphrases await got('https://example.com', { https: { key: [ {pem: fs.readFileSync('./client_key1.pem'), passphrase: 'passphrase1'}, {pem: fs.readFileSync('./client_key2.pem'), passphrase: 'passphrase2'}, ], certificate: [ fs.readFileSync('./client_cert1.pem'), fs.readFileSync('./client_cert2.pem') ] } }); // Single encrypted PFX with passphrase await got('https://example.com', { https: { pfx: fs.readFileSync('./fake.pfx'), passphrase: 'passphrase' } }); // Multiple encrypted PFX's with different passphrases await got('https://example.com', { https: { pfx: [ { buffer: fs.readFileSync('./key1.pfx'), passphrase: 'passphrase1' }, { buffer: fs.readFileSync('./key2.pfx'), passphrase: 'passphrase2' } ] } }); // Multiple encrypted PFX's with single passphrase await got('https://example.com', { https: { passphrase: 'passphrase', pfx: [ { buffer: fs.readFileSync('./key1.pfx') }, { buffer: fs.readFileSync('./key2.pfx') } ] } }); ``` --- ## File: documentation/6-timeout.md [> Back to homepage](../readme.md#documentation) ## Timeout options Source code: [`source/core/timed-out.ts`](../source/core/timed-out.ts) It is a good practice to set a timeout to prevent hanging requests.\ By default, there is no timeout set. Note: The [`retry` configuration](7-retry.md) also applies to timeouts. **All numbers refer to milliseconds.** ```js import got from 'got'; const {timings} = await got('https://example.com', { timeout: { lookup: 100, connect: 50, secureConnect: 50, socket: 1000, send: 10000, response: 1000 } }); // Alternatively: const {timings} = await got('https://example.com', { timeout: { request: 10000 } }); console.log(timings); // { // start: 1625474926602, // socket: 1625474926605, // lookup: 1625474926610, // connect: 1625474926617, // secureConnect: 1625474926631, // upload: 1625474926631, // response: 1625474926638, // end: 1625474926642, // error: undefined, // abort: undefined, // phases: { // wait: 3, // dns: 5, // tcp: 7, // tls: 14, // request: 0, // firstByte: 7, // download: 4, // total: 40 // } // } ``` ### `timeout` **Type: `object`** This object describes the maximum allowed time for particular events. #### `lookup` **Type: `number`** Starts when a socket is assigned.\ Ends when the hostname has been resolved. Does not apply when using a Unix domain socket.\ Does not apply when passing an IP address. It is preferred to not use any greater value than `100`. #### `connect` **Type: `number`** Starts when lookup completes.\ Ends when the socket is fully connected. If `lookup` does not apply to the request, this event starts when the socket is assigned and ends when the socket is connected. #### `secureConnect` **Type: `number`** Starts when `connect` completes.\ Ends when the handshake process completes. This timeout applies only to HTTPS requests. #### `socket` **Type: `number`** Starts when the socket is connected.\ Resets when new data is transferred. It is the same as [`request.setTimeout(timeout)`](https://nodejs.org/api/http.html#http_request_settimeout_timeout_callback) which calls [`socket.setTimeout(timeout)`](https://nodejs.org/api/net.html#socketsettimeouttimeout-callback) after a socket is assigned to this request and is connected. #### `send` **Type: `number`** Starts when the socket is connected.\ Ends when all data have been written to the socket. **Note:** > - This does not assure the data have been received by the other end! > - It only assures that the data have been passed to the underlying OS. #### `response` **Type: `number`** Starts when request has been flushed.\ Ends when the headers are received. #### ~~`read`~~ **Type: `number`** Starts when the headers are received.\ Ends when the response's `end` event fires. **Note:** > - This timeout is blocked by https://github.com/nodejs/node/issues/35923 #### `request` **Type: `number`** Starts when the request is initiated.\ Ends when the response's `end` event fires. In other words, this is the global timeout. --- METRICS --- - Files Extracted: 11 - Estimated Token Budget: ~24921 tokens - Recency Window: Active (< 180 days) - Canonical Reference: https://codewiki.google/github.com/sindresorhus/got