UNPKG

60.3 kBMarkdownView Raw
1<div align="center">
2 <br>
3 <br>
4 <img width="360" src="media/logo.svg" alt="Got">
5 <br>
6 <em><strong>+ caseless</strong></em>
7 <br>
8 <br>
9 <p align="center">Huge thanks to <a href="https://moxy.studio"><img src="https://sindresorhus.com/assets/thanks/moxy-logo.svg" width="150"></a> for sponsoring Sindre Sorhus!
10 </p>
11 <br>
12 <br>
13</div>
14
15
16> Human-friendly and powerful HTTP request library for Node.js
17> Caseless fork - Preserves the casing of your headers.
18
19[![Build Status: Linux](https://travis-ci.org/forivall/got.svg?branch=caseless)](https://travis-ci.org/forivall/got)
20[![Coverage Status](https://coveralls.io/repos/github/forivall/got/badge.svg?branch=caseless)](https://coveralls.io/github/forivall/got?branch=caseless)
21[![Downloads](https://img.shields.io/npm/dm/got-caseless.svg)](https://npmjs.com/got-caseless)
22[![Install size](https://packagephobia.now.sh/badge?p=got-caseless)](https://packagephobia.now.sh/result?p=got-caseless)
23
24[Moving from Request?](documentation/migration-guides.md) [*(Note that Request is unmaintained)*](https://github.com/request/request/issues/3142)
25
26[See how Got compares to other HTTP libraries](#comparison)
27
28For browser usage, we recommend [Ky](https://github.com/sindresorhus/ky) by the same people.
29
30## Highlights
31
32- [Promise API](#api)
33- [Stream API](#streams)
34- [Pagination API (experimental)](#pagination)
35- [Request cancelation](#aborting-the-request)
36- [RFC compliant caching](#cache-adapters)
37- [Follows redirects](#followredirect)
38- [Retries on failure](#retry)
39- [Progress events](#onuploadprogress-progress)
40- [Handles gzip/deflate/brotli](#decompress)
41- [Timeout handling](#timeout)
42- [Errors with metadata](#errors)
43- [JSON mode](#json-mode)
44- [WHATWG URL support](#url)
45- [Hooks](#hooks)
46- [Instances with custom defaults](#instances)
47- [Types](#types)
48- [Composable](documentation/advanced-creation.md#merging-instances)
49- [Plugins](documentation/lets-make-a-plugin.md)
50- [Used by 3000+ packages and 1.6M+ repos](https://github.com/sindresorhus/got/network/dependents)
51- Actively maintained
52
53## Install
54
55```
56$ npm install got
57```
58
59## Usage
60
61```js
62const got = require('got');
63
64(async () => {
65 try {
66 const response = await got('https://sindresorhus.com');
67 console.log(response.body);
68 //=> '<!doctype html> ...'
69 } catch (error) {
70 console.log(error.response.body);
71 //=> 'Internal server error ...'
72 }
73})();
74```
75
76###### Streams
77
78```js
79const stream = require('stream');
80const {promisify} = require('util');
81const fs = require('fs');
82const got = require('got');
83
84const pipeline = promisify(stream.pipeline);
85
86(async () => {
87 await pipeline(
88 got.stream('https://sindresorhus.com'),
89 fs.createWriteStream('index.html')
90 );
91
92 // For POST, PUT, and PATCH methods `got.stream` returns a `stream.Writable`
93 await pipeline(
94 fs.createReadStream('index.html'),
95 got.stream.post('https://sindresorhus.com')
96 );
97})();
98```
99
100**Tip:** Using `from.pipe(to)` doesn't forward errors. If you use it, switch to [`Stream.pipeline(from, ..., to, callback)`](https://nodejs.org/api/stream.html#stream_stream_pipeline_streams_callback) instead (available from Node v10).
101
102### API
103
104It's a `GET` request by default, but can be changed by using different methods or via `options.method`.
105
106**By default, Got will retry on failure. To disable this option, set [`options.retry`](#retry) to `0`.**
107
108#### got(url?, options?)
109
110Returns a Promise for a [`response` object](#response) or a [stream](#streams-1) if `options.isStream` is set to true.
111
112##### url
113
114Type: `string | object`
115
116The URL to request, as a string, a [`https.request` options object](https://nodejs.org/api/https.html#https_https_request_options_callback), or a [WHATWG `URL`](https://nodejs.org/api/url.html#url_class_url).
117
118Properties from `options` will override properties in the parsed `url`.
119
120If no protocol is specified, it will throw a `TypeError`.
121
122**Note:** this can also be an option.
123
124##### options
125
126Type: `object`
127
128Any of the [`https.request`](https://nodejs.org/api/https.html#https_https_request_options_callback) options.
129
130**Note:** Legacy URL support is disabled. `options.path` is supported only for backwards compatibility. Use `options.pathname` and `options.searchParams` instead. `options.auth` has been replaced with `options.username` & `options.password`.
131
132###### prefixUrl
133
134Type: `string | URL`
135
136When specified, `prefixUrl` will be prepended to `url`. The prefix can be any valid URL, either relative or absolute. A trailing slash `/` is optional - one will be added automatically.
137
138**Note:** `prefixUrl` will be ignored if the `url` argument is a URL instance.
139
140**Note:** Leading slashes in `input` are disallowed when using this option 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.
141
142**Tip:** Useful when used with [`got.extend()`](#custom-endpoints) to create niche-specific Got-instances.
143
144**Tip:** You can change `prefixUrl` using hooks as long as the URL still includes the `prefixUrl`. If the URL doesn't include it anymore, it will throw.
145
146```js
147const got = require('got');
148
149(async () => {
150 await got('unicorn', {prefixUrl: 'https://cats.com'});
151 //=> 'https://cats.com/unicorn'
152
153 const instance = got.extend({
154 prefixUrl: 'https://google.com'
155 });
156
157 await instance('unicorn', {
158 hooks: {
159 beforeRequest: [
160 options => {
161 options.prefixUrl = 'https://cats.com';
162 }
163 ]
164 }
165 });
166 //=> 'https://cats.com/unicorn'
167})();
168```
169
170###### headers
171
172Type: `object`\
173Default: `{}`
174
175Request headers.
176
177Existing headers will be overwritten. Headers set to `undefined` will be omitted.
178
179###### isStream
180
181Type: `boolean`\
182Default: `false`
183
184Returns a `Stream` instead of a `Promise`. This is equivalent to calling `got.stream(url, options?)`.
185
186###### body
187
188Type: `string | Buffer | stream.Readable` or [`form-data` instance](https://github.com/form-data/form-data)
189
190**Note #1:** The `body` option cannot be used with the `json` or `form` option.
191
192**Note #2:** If you provide this option, `got.stream()` will be read-only.
193
194**Note #3:** If you provide a payload with the `GET` or `HEAD` method, it will throw a `TypeError`.
195
196The `content-length` header will be automatically set if `body` is a `string` / `Buffer` / `fs.createReadStream` instance / [`form-data` instance](https://github.com/form-data/form-data), and `content-length` and `transfer-encoding` are not manually set in `options.headers`.
197
198###### json
199
200Type: `object | Array | number | string | boolean | null` *(JSON-serializable values)*
201
202**Note:** If you provide this option, `got.stream()` will be read-only.
203
204JSON body. If the `Content-Type` header is not set, it will be set to `application/json`.
205
206###### context
207
208Type: `object`
209
210User data. In contrast to other options, `context` is not enumerable.
211
212**Note:** The object is never merged, it's just passed through. Got will not modify the object in any way.
213
214It's very useful for storing auth tokens:
215
216```js
217const got = require('got');
218
219const instance = got.extend({
220 hooks: {
221 beforeRequest: [
222 options => {
223 if (!options.context && !options.context.token) {
224 throw new Error('Token required');
225 }
226
227 options.setHeader('token') = options.context.token;
228 }
229 ]
230 }
231});
232
233(async () => {
234 const context = {
235 token: 'secret'
236 };
237
238 const response = await instance('https://httpbin.org/headers', {context});
239
240 // Let's see the headers
241 console.log(response.body);
242})();
243```
244
245###### responseType
246
247Type: `string`\
248Default: `'text'`
249
250**Note:** When using streams, this option is ignored.
251
252The parsing method. Can be `'text'`, `'json'` or `'buffer'`.
253
254The promise also has `.text()`, `.json()` and `.buffer()` methods which sets this and the `resolveBodyOnly` option automatically.
255
256Example:
257
258```js
259// This
260const body = await got(url).json();
261
262// is the same as this
263const body = await got(url, {responseType: 'json', resolveBodyOnly: true});
264```
265
266###### resolveBodyOnly
267
268Type: `string`\
269Default: `false`
270
271When set to `true` the promise will return the [Response body](#body-1) instead of the [Response](#response) object.
272
273###### cookieJar
274
275Type: `object` | [`tough.CookieJar` instance](https://github.com/salesforce/tough-cookie#cookiejar)
276
277**Note:** If you provide this option, `options.headers.cookie` will be overridden.
278
279Cookie support. You don't have to care about parsing or how to store them. [Example](#cookies).
280
281###### cookieJar.setCookie
282
283Type: `Function<Promise>`
284
285The function takes two arguments: `rawCookie` (`string`) and `url` (`string`).
286
287###### cookieJar.getCookieString
288
289Type: `Function<Promise>`
290
291The function takes one argument: `url` (`string`).
292
293###### ignoreInvalidCookies
294
295Type: `boolean`\
296Default: `false`
297
298Ignore invalid cookies instead of throwing an error. Only useful when the `cookieJar` option has been set. Not recommended.
299
300###### encoding
301
302Type: `string`\
303Default: `'utf8'`
304
305[Encoding](https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings) to be used on `setEncoding` of the response data.
306
307To get a [`Buffer`](https://nodejs.org/api/buffer.html), you need to set [`responseType`](#responseType) to `buffer` instead.
308
309###### form
310
311Type: `object | true`
312
313**Note:** If you provide this option, `got.stream()` will be read-only.
314
315The form body is converted to query string using [`(new URLSearchParams(object)).toString()`](https://nodejs.org/api/url.html#url_constructor_new_urlsearchparams_obj).
316
317If set to `true` and the `Content-Type` header is not set, it will be set to `application/x-www-form-urlencoded`.
318
319###### searchParams
320
321Type: `string | object<string, string | number> | URLSearchParams`
322
323Query string that will be added to the request URL. This will override the query string in `url`.
324
325If you need to pass in an array, you can do it using a `URLSearchParams` instance:
326
327```js
328const got = require('got');
329
330const searchParams = new URLSearchParams([['key', 'a'], ['key', 'b']]);
331
332got('https://example.com', {searchParams});
333
334console.log(searchParams.toString());
335//=> 'key=a&key=b'
336```
337
338And if you need a different array format, you could use the [`query-string`](https://github.com/sindresorhus/query-string) package:
339
340```js
341const got = require('got');
342const queryString = require('query-string');
343
344const searchParams = queryString.stringify({key: ['a', 'b']}, {arrayFormat: 'bracket'});
345
346got('https://example.com', {searchParams});
347
348console.log(searchParams);
349//=> 'key[]=a&key[]=b'
350```
351
352###### timeout
353
354Type: `number | object`
355
356Milliseconds to wait for the server to end the response before aborting the request with [`got.TimeoutError`](#gottimeouterror) error (a.k.a. `request` property). By default, there's no timeout.
357
358This also accepts an `object` with the following fields to constrain the duration of each phase of the request lifecycle:
359
360- `lookup` starts when a socket is assigned and ends when the hostname has been resolved. Does not apply when using a Unix domain socket.
361- `connect` starts when `lookup` completes (or when the socket is assigned if lookup does not apply to the request) and ends when the socket is connected.
362- `secureConnect` starts when `connect` completes and ends when the handshaking process completes (HTTPS only).
363- `socket` starts when the socket is connected. See [request.setTimeout](https://nodejs.org/api/http.html#http_request_settimeout_timeout_callback).
364- `response` starts when the request has been written to the socket and ends when the response headers are received.
365- `send` starts when the socket is connected and ends with the request has been written to the socket.
366- `request` starts when the request is initiated and ends when the response's end event fires.
367
368###### retry
369
370Type: `number | object`\
371Default:
372- limit: `2`
373- calculateDelay: `({attemptCount, retryOptions, error, computedValue}) => computedValue`
374- methods: `GET` `PUT` `HEAD` `DELETE` `OPTIONS` `TRACE`
375- statusCodes: [`408`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/408) [`413`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/413) [`429`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429) [`500`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/500) [`502`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/502) [`503`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/503) [`504`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/504) [`521`](https://support.cloudflare.com/hc/en-us/articles/115003011431#521error) [`522`](https://support.cloudflare.com/hc/en-us/articles/115003011431#522error) [`524`](https://support.cloudflare.com/hc/en-us/articles/115003011431#524error)
376- maxRetryAfter: `undefined`
377- errorCodes: `ETIMEDOUT` `ECONNRESET` `EADDRINUSE` `ECONNREFUSED` `EPIPE` `ENOTFOUND` `ENETUNREACH` `EAI_AGAIN`
378
379An object representing `limit`, `calculateDelay`, `methods`, `statusCodes`, `maxRetryAfter` and `errorCodes` fields for maximum retry count, retry handler, allowed methods, allowed status codes, maximum [`Retry-After`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) time and allowed error codes.
380
381**Note:** When using streams, this option is ignored. If the connection is reset when downloading, you need to catch the error and clear the file you were writing into to prevent duplicated content.
382
383If `maxRetryAfter` is set to `undefined`, it will use `options.timeout`.\
384If [`Retry-After`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) header is greater than `maxRetryAfter`, it will cancel the request.
385
386Delays between retries counts with function `1000 * Math.pow(2, retry) + Math.random() * 100`, where `retry` is attempt number (starts from 1).
387
388The `calculateDelay` property is a `function` that receives an object with `attemptCount`, `retryOptions`, `error` and `computedValue` properties for current retry count, the retry options, error and default computed value. The function must return a delay in milliseconds (`0` return value cancels retry).
389
390By default, it retries *only* on the specified methods, status codes, and on these network errors:
391- `ETIMEDOUT`: One of the [timeout](#timeout) limits were reached.
392- `ECONNRESET`: Connection was forcibly closed by a peer.
393- `EADDRINUSE`: Could not bind to any free port.
394- `ECONNREFUSED`: Connection was refused by the server.
395- `EPIPE`: The remote side of the stream being written has been closed.
396- `ENOTFOUND`: Couldn't resolve the hostname to an IP address.
397- `ENETUNREACH`: No internet connection.
398- `EAI_AGAIN`: DNS lookup timed out.
399
400###### followRedirect
401
402Type: `boolean`\
403Default: `true`
404
405Defines if redirect responses should be followed automatically.
406
407Note that if a `303` is sent by the server in response to any request type (`POST`, `DELETE`, etc.), Got will automatically request the resource pointed to in the location header via `GET`. This is in accordance with [the spec](https://tools.ietf.org/html/rfc7231#section-6.4.4).
408
409###### methodRewriting
410
411Type: `boolean`\
412Default: `true`
413
414By default, redirects will use [method rewriting](https://tools.ietf.org/html/rfc7231#section-6.4). For example, when sending a POST request and receiving a `302`, it will resend the body to the new location using the same HTTP method (`POST` in this case).
415
416###### maxRedirects
417
418Type: `number`\
419Default: `10`
420
421If exceeded, the request will be aborted and a `MaxRedirectsError` will be thrown.
422
423###### decompress
424
425Type: `boolean`\
426Default: `true`
427
428Decompress the response automatically. This will set the `accept-encoding` header to `gzip, deflate, br` on Node.js 11.7.0+ or `gzip, deflate` for older Node.js versions, unless you set it yourself.
429
430Brotli (`br`) support requires Node.js 11.7.0 or later.
431
432If this is disabled, a compressed response is returned as a `Buffer`. This may be useful if you want to handle decompression yourself or stream the raw compressed data.
433
434###### cache
435
436Type: `object`\
437Default: `false`
438
439[Cache adapter instance](#cache-adapters) for storing cached response data.
440
441###### dnsCache
442
443Type: `object`\
444Default: `false`
445
446[Cache adapter instance](#cache-adapters) for storing cached DNS data.
447
448###### request
449
450Type: `Function`\
451Default: `http.request | https.request` *(Depending on the protocol)*
452
453Custom request function. The main purpose of this is to [support HTTP2 using a wrapper](#experimental-http2-support).
454
455###### useElectronNet
456
457Type: `boolean`\
458Default: `false`
459
460[**Deprecated**](https://github.com/sindresorhus/got#electron-support-has-been-deprecated)
461
462When used in Electron, Got will use [`electron.net`](https://electronjs.org/docs/api/net/) instead of the Node.js `http` module. According to the Electron docs, it should be fully compatible, but it's not entirely. See [#443](https://github.com/sindresorhus/got/issues/443) and [#461](https://github.com/sindresorhus/got/issues/461).
463
464###### throwHttpErrors
465
466Type: `boolean`\
467Default: `true`
468
469Determines if a `got.HTTPError` is thrown for error responses (non-2xx status codes).
470
471If 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.
472
473###### agent
474
475Same as the [`agent` option](https://nodejs.org/api/http.html#http_http_request_url_options_callback) for `http.request`, but with an extra feature:
476
477If you require different agents for different protocols, you can pass a map of agents to the `agent` option. This is necessary because a request to one protocol might redirect to another. In such a scenario, Got will switch over to the right protocol agent for you.
478
479```js
480const got = require('got');
481const HttpAgent = require('agentkeepalive');
482const {HttpsAgent} = HttpAgent;
483
484got('https://sindresorhus.com', {
485 agent: {
486 http: new HttpAgent(),
487 https: new HttpsAgent()
488 }
489});
490```
491
492###### hooks
493
494Type: `object<string, Function[]>`
495
496Hooks allow modifications during the request lifecycle. Hook functions may be async and are run serially.
497
498###### hooks.init
499
500Type: `Function[]`\
501Default: `[]`
502
503Called with plain [request options](#options), right before their normalization. This is especially useful in conjunction with [`got.extend()`](#instances) when the input needs custom handling.
504
505See the [Request migration guide](documentation/migration-guides.md#breaking-changes) for an example.
506
507**Note:** This hook must be synchronous!
508
509###### hooks.beforeRequest
510
511Type: `Function[]`\
512Default: `[]`
513
514Called with [normalized](source/normalize-arguments.ts) [request options](#options). Got will make no further changes to the request before it is sent (except the body serialization). This is especially useful in conjunction with [`got.extend()`](#instances) when you want to create an API client that, for example, uses HMAC-signing.
515
516See the [AWS section](#aws) for an example.
517
518###### hooks.beforeRedirect
519
520Type: `Function[]`\
521Default: `[]`
522
523Called with [normalized](source/normalize-arguments.ts) [request options](#options) and the redirect [response](#response). Got will make no further changes to the request. This is especially useful when you want to avoid dead sites. Example:
524
525```js
526const got = require('got');
527
528got('https://example.com', {
529 hooks: {
530 beforeRedirect: [
531 (options, response) => {
532 if (options.hostname === 'deadSite') {
533 options.hostname = 'fallbackSite';
534 }
535 }
536 ]
537 }
538});
539```
540
541###### hooks.beforeRetry
542
543Type: `Function[]`\
544Default: `[]`
545
546**Note:** When using streams, this hook is ignored.
547
548Called with [normalized](source/normalize-arguments.ts) [request options](#options), the error and the retry count. Got will make no further changes to the request. This is especially useful when some extra work is required before the next try. Example:
549
550```js
551const got = require('got');
552
553got.post('https://example.com', {
554 hooks: {
555 beforeRetry: [
556 (options, error, retryCount) => {
557 if (error.statusCode === 413) { // Payload too large
558 options.body = getNewBody();
559 }
560 }
561 ]
562 }
563});
564```
565
566**Note:** When retrying in a `afterResponse` hook, all remaining `beforeRetry` hooks will be called without the `error` and `retryCount` arguments.
567
568###### hooks.afterResponse
569
570Type: `Function[]`\
571Default: `[]`
572
573**Note:** When using streams, this hook is ignored.
574
575Called with [response object](#response) and a retry function. Calling the retry function will trigger `beforeRetry` hooks.
576
577Each function should return the response. This is especially useful when you want to refresh an access token. Example:
578
579```js
580const got = require('got');
581
582const instance = got.extend({
583 hooks: {
584 afterResponse: [
585 (response, retryWithMergedOptions) => {
586 if (response.statusCode === 401) { // Unauthorized
587 const updatedOptions = {
588 headers: {
589 token: getNewToken() // Refresh the access token
590 }
591 };
592
593 // Save for further requests
594 instance.defaults.options = got.mergeOptions(instance.defaults.options, updatedOptions);
595
596 // Make a new retry
597 return retryWithMergedOptions(updatedOptions);
598 }
599
600 // No changes otherwise
601 return response;
602 }
603 ],
604 beforeRetry: [
605 (options, error, retryCount) => {
606 // This will be called on `retryWithMergedOptions(...)`
607 }
608 ]
609 },
610 mutableDefaults: true
611});
612```
613
614###### hooks.beforeError
615
616Type: `Function[]`\
617Default: `[]`
618
619Called with an `Error` instance. The error is passed to the hook right before it's thrown. This is especially useful when you want to have more detailed errors.
620
621**Note:** Errors thrown while normalizing input options are thrown directly and not part of this hook.
622
623```js
624const got = require('got');
625
626got('https://api.github.com/some-endpoint', {
627 hooks: {
628 beforeError: [
629 error => {
630 const {response} = error;
631 if (response && response.body) {
632 error.name = 'GitHubError';
633 error.message = `${response.body.message} (${error.statusCode})`;
634 }
635
636 return error;
637 }
638 ]
639 }
640});
641```
642
643##### \_pagination
644
645Type: `object`
646
647**Note:** This feature is marked as experimental as we're [looking for feedback](https://github.com/sindresorhus/got/issues/1052) on the API and how it works. The feature itself is stable, but the API may change based on feedback. So if you decide to try it out, we suggest locking down the `got` dependency semver range or use a lockfile.
648
649###### \_pagination.transform
650
651Type: `Function`\
652Default: `response => JSON.parse(response.body)`
653
654A function that transform [`Response`](#response) into an array of items. This is where you should do the parsing.
655
656###### \_pagination.paginate
657
658Type: `Function`\
659Default: [`Link` header logic](source/index.ts)
660
661A function that returns an object representing Got options pointing to the next page. If there are no more pages, `false` should be returned.
662
663###### \_pagination.filter
664
665Type: `Function`\
666Default: `(item, allItems) => true`
667
668Checks whether the item should be emitted or not.
669
670###### \_pagination.shouldContinue
671
672Type: `Function`\
673Default: `(item, allItems) => true`
674
675Checks whether the pagination should continue.
676
677For example, if you need to stop **before** emitting an entry with some flag, you should use `(item, allItems) => !item.flag`. If you want to stop **after** emitting the entry, you should use `(item, allItems) => allItems.some(entry => entry.flag)` instead.
678
679###### \_pagination.countLimit
680
681Type: `number`\
682Default: `Infinity`
683
684The maximum amount of items that should be emitted.
685
686#### Response
687
688The response object will typically be a [Node.js HTTP response stream](https://nodejs.org/api/http.html#http_class_http_incomingmessage), however, if returned from the cache it will be a [response-like object](https://github.com/lukechilds/responselike) which behaves in the same way.
689
690##### request
691
692Type: `object`
693
694**Note:** This is not a [http.ClientRequest](https://nodejs.org/api/http.html#http_class_http_clientrequest).
695
696- `options` - The Got options that were set on this request.
697
698##### body
699
700Type: `string | object | Buffer` *(Depending on `options.responseType`)*
701
702The result of the request.
703
704##### url
705
706Type: `string`
707
708The request URL or the final URL after redirects.
709
710##### ip
711
712Type: `string`
713
714The remote IP address.
715
716**Note:** Not available when the response is cached. This is hopefully a temporary limitation, see [lukechilds/cacheable-request#86](https://github.com/lukechilds/cacheable-request/issues/86).
717
718##### requestUrl
719
720Type: `string`
721
722The original request URL.
723
724##### timings
725
726Type: `object`
727
728The object contains the following properties:
729
730- `start` - Time when the request started.
731- `socket` - Time when a socket was assigned to the request.
732- `lookup` - Time when the DNS lookup finished.
733- `connect` - Time when the socket successfully connected.
734- `secureConnect` - Time when the socket securely connected.
735- `upload` - Time when the request finished uploading.
736- `response` - Time when the request fired `response` event.
737- `end` - Time when the response fired `end` event.
738- `error` - Time when the request fired `error` event.
739- `abort` - Time when the request fired `abort` event.
740- `phases`
741 - `wait` - `timings.socket - timings.start`
742 - `dns` - `timings.lookup - timings.socket`
743 - `tcp` - `timings.connect - timings.lookup`
744 - `tls` - `timings.secureConnect - timings.connect`
745 - `request` - `timings.upload - (timings.secureConnect || timings.connect)`
746 - `firstByte` - `timings.response - timings.upload`
747 - `download` - `timings.end - timings.response`
748 - `total` - `(timings.end || timings.error || timings.abort) - timings.start`
749
750If something has not been measured yet, it will be `undefined`.
751
752**Note:** The time is a `number` representing the milliseconds elapsed since the UNIX epoch.
753
754##### isFromCache
755
756Type: `boolean`
757
758Whether the response was retrieved from the cache.
759
760##### redirectUrls
761
762Type: `string[]`
763
764The redirect URLs.
765
766##### retryCount
767
768Type: `number`
769
770The number of times the request was retried.
771
772#### Streams
773
774**Note:** Progress events, redirect events and request/response events can also be used with promises.
775
776**Note:** To access `response.isFromCache` you need to use `got.stream(url, options).isFromCache`. The value will be undefined until the `response` event.
777
778#### got.stream(url, options?)
779
780Sets `options.isStream` to `true`.
781
782Returns a [duplex stream](https://nodejs.org/api/stream.html#stream_class_stream_duplex) with additional events:
783
784##### .on('request', request)
785
786`request` event to get the request object of the request.
787
788**Tip:** You can use `request` event to abort request:
789
790```js
791got.stream('https://github.com')
792 .on('request', request => setTimeout(() => request.abort(), 50));
793```
794
795##### .on('response', response)
796
797The `response` event to get the response object of the final request.
798
799##### .on('redirect', response, nextOptions)
800
801The `redirect` event to get the response object of a redirect. The second argument is options for the next request to the redirect location.
802
803##### .on('uploadProgress', progress)
804##### .on('downloadProgress', progress)
805
806Progress events for uploading (sending a request) and downloading (receiving a response). The `progress` argument is an object like:
807
808```js
809{
810 percent: 0.1,
811 transferred: 1024,
812 total: 10240
813}
814```
815
816If the `content-length` header is missing, `total` will be `undefined`.
817
818```js
819(async () => {
820 const response = await got('https://sindresorhus.com')
821 .on('downloadProgress', progress => {
822 // Report download progress
823 })
824 .on('uploadProgress', progress => {
825 // Report upload progress
826 });
827
828 console.log(response);
829})();
830```
831
832##### .on('error', error, body, response)
833
834The `error` event emitted in case of a protocol error (like `ENOTFOUND` etc.) or status error (4xx or 5xx). The second argument is the body of the server response in case of status error. The third argument is a response object.
835
836#### Pagination
837
838#### got.paginate(url, options?)
839
840Returns an async iterator:
841
842```js
843(async () => {
844 const countLimit = 10;
845
846 const pagination = got.paginate('https://api.github.com/repos/sindresorhus/got/commits', {
847 _pagination: {countLimit}
848 });
849
850 console.log(`Printing latest ${countLimit} Got commits (newest to oldest):`);
851
852 for await (const commitData of pagination) {
853 console.log(commitData.commit.message);
854 }
855})();
856```
857
858See [`options._pagination`](#_pagination) for more pagination options.
859
860#### got.get(url, options?)
861#### got.post(url, options?)
862#### got.put(url, options?)
863#### got.patch(url, options?)
864#### got.head(url, options?)
865#### got.delete(url, options?)
866
867Sets `options.method` to the method name and makes a request.
868
869### Instances
870
871#### got.extend(...options)
872
873Configure a new `got` instance with default `options`. The `options` are merged with the parent instance's `defaults.options` using [`got.mergeOptions`](#gotmergeoptionsparentoptions-newoptions). You can access the resolved options with the `.defaults` property on the instance.
874
875```js
876const client = got.extend({
877 prefixUrl: 'https://example.com',
878 headers: {
879 'x-unicorn': 'rainbow'
880 }
881});
882
883client.get('demo');
884
885/* HTTP Request =>
886 * GET /demo HTTP/1.1
887 * Host: example.com
888 * x-unicorn: rainbow
889 */
890```
891
892```js
893(async () => {
894 const client = got.extend({
895 prefixUrl: 'httpbin.org',
896 headers: {
897 'x-foo': 'bar'
898 }
899 });
900 const {headers} = await client.get('headers').json();
901 //=> headers['x-foo'] === 'bar'
902
903 const jsonClient = client.extend({
904 responseType: 'json',
905 resolveBodyOnly: true,
906 headers: {
907 'x-baz': 'qux'
908 }
909 });
910 const {headers: headers2} = await jsonClient.get('headers');
911 //=> headers2['x-foo'] === 'bar'
912 //=> headers2['x-baz'] === 'qux'
913})();
914```
915
916Additionally, `got.extend()` accepts two properties from the `defaults` object: `mutableDefaults` and `handlers`. Example:
917
918```js
919// You can now modify `mutableGot.defaults.options`.
920const mutableGot = got.extend({mutableDefaults: true});
921
922const mergedHandlers = got.extend({
923 handlers: [
924 (options, next) => {
925 options.getHeader('referer');
926
927 return next(options);
928 }
929 ]
930});
931```
932
933**Note:** Handlers can be asynchronous. The recommended approach is:
934
935```js
936const handler = (options, next) => {
937 if (options.stream) {
938 // It's a Stream
939 return next(options);
940 }
941
942 // It's a Promise
943 return (async () => {
944 try {
945 const response = await next(options);
946 response.yourOwnProperty = true;
947 return response;
948 } catch (error) {
949 // Every error will be replaced by this one.
950 // Before you receive any error here,
951 // it will be passed to the `beforeError` hooks first.
952 // Note: this one won't be passed to `beforeError` hook. It's final.
953 throw new Error('Your very own error.');
954 }
955 })();
956};
957
958const instance = got.extend({handlers: [handler]});
959```
960
961#### got.extend(...instances)
962
963Merges many instances into a single one:
964- options are merged using [`got.mergeOptions()`](#gotmergeoptionsparentoptions-newoptions) (+ hooks are merged too),
965- handlers are stored in an array (you can access them through `instance.defaults.handlers`).
966
967#### got.extend(...options, ...instances, ...)
968
969It's possible to combine options and instances.\
970It gives the same effect as `got.extend(...options).extend(...instances)`:
971
972```js
973const a = {headers: {cat: 'meow'}};
974const b = got.extend({
975 options: {
976 headers: {
977 cow: 'moo'
978 }
979 }
980});
981
982// The same as `got.extend(a).extend(b)`.
983// Note `a` is options and `b` is an instance.
984got.extend(a, b);
985//=> {headers: {cat: 'meow', cow: 'moo'}}
986```
987
988#### got.mergeOptions(parentOptions, newOptions)
989
990Extends parent options. Avoid using [object spread](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) as it doesn't work recursively:
991
992```js
993const a = {headers: {cat: 'meow', wolf: ['bark', 'wrrr']}};
994const b = {headers: {cow: 'moo', wolf: ['auuu']}};
995
996{...a, ...b} // => {headers: {cow: 'moo', wolf: ['auuu']}}
997got.mergeOptions(a, b) // => {headers: {cat: 'meow', cow: 'moo', wolf: ['auuu']}}
998```
999
1000Options are deeply merged to a new object. The value of each key is determined as follows:
1001
1002- If the new property is set to `undefined`, it keeps the old one.
1003- If both properties are an instances of `URLSearchParams`, a new URLSearchParams instance is created. The values are merged using [`urlSearchParams.append(key, value)`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/append).
1004- If the parent property is an instance of `URL` and the new value is a `string` or `URL`, a new URL instance is created: [`new URL(new, parent)`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL#Syntax).
1005- If the new property is a plain `object`:
1006 - If the parent property is a plain `object` too, both values are merged recursively into a new `object`.
1007 - Otherwise, only the new value is deeply cloned.
1008- If the new property is an `Array`, it overwrites the old one with a deep clone of the new property.
1009- Otherwise, the new value is assigned to the key.
1010
1011#### got.defaults
1012
1013Type: `object`
1014
1015The Got defaults used in that instance.
1016
1017##### [options](#options)
1018
1019##### handlers
1020
1021Type: `Function[]`\
1022Default: `[]`
1023
1024An array of functions. You execute them directly by calling `got()`. They are some sort of "global hooks" - these functions are called first. The last handler (*it's hidden*) is either [`asPromise`](source/as-promise.ts) or [`asStream`](source/as-stream.ts), depending on the `options.isStream` property.
1025
1026Each handler takes two arguments:
1027
1028###### [options](#options)
1029
1030###### next()
1031
1032Returns a `Promise` or a `Stream` depending on [`options.isStream`](#isstream).
1033
1034```js
1035const settings = {
1036 handlers: [
1037 (options, next) => {
1038 if (options.isStream) {
1039 // It's a Stream, so we can perform stream-specific actions on it
1040 return next(options)
1041 .on('request', request => {
1042 setTimeout(() => {
1043 request.abort();
1044 }, 50);
1045 });
1046 }
1047
1048 // It's a Promise
1049 return next(options);
1050 }
1051 ],
1052 options: got.mergeOptions(got.defaults.options, {
1053 responseType: 'json'
1054 })
1055};
1056
1057const jsonGot = got.extend(settings);
1058```
1059
1060##### mutableDefaults
1061
1062Type: `boolean`\
1063Default: `false`
1064
1065A read-only boolean describing whether the defaults are mutable or not. If set to `true`, you can [update headers over time](#hooksafterresponse), for example, update an access token when it expires.
1066
1067## Types
1068
1069Got exports some handy TypeScript types and interfaces. See the type definition for all the exported types.
1070
1071### Got
1072
1073TypeScript will automatically infer types for Got instances, but in case you want to define something like dependencies, you can import the available types directly from Got.
1074
1075```ts
1076import {GotRequestMethod} from 'got';
1077
1078interface Dependencies {
1079 readonly post: GotRequestMethod
1080}
1081```
1082
1083### Hooks
1084
1085When writing hooks, you can refer to their types to keep your interfaces consistent.
1086
1087```ts
1088import {BeforeRequestHook} from 'got';
1089
1090const addAccessToken = (accessToken: string): BeforeRequestHook => options => {
1091 options.path = `${options.path}?access_token=${accessToken}`;
1092}
1093```
1094
1095## Errors
1096
1097Each error contains an `options` property which are the options Got used to create a request - just to make debugging easier.
1098
1099#### got.CacheError
1100
1101When a cache method fails, for example, if the database goes down or there's a filesystem error.
1102
1103#### got.RequestError
1104
1105When a request fails. Contains a `code` property with error class code, like `ECONNREFUSED`.
1106
1107#### got.ReadError
1108
1109When reading from response stream fails.
1110
1111#### got.ParseError
1112
1113When server response code is 2xx, and parsing body fails. Includes a `response` property.
1114
1115#### got.HTTPError
1116
1117When the server response code is not 2xx. Includes a `response` property.
1118
1119#### got.MaxRedirectsError
1120
1121When the server redirects you more than ten times. Includes a `response` property.
1122
1123#### got.UnsupportedProtocolError
1124
1125When given an unsupported protocol.
1126
1127#### got.CancelError
1128
1129When the request is aborted with `.cancel()`.
1130
1131#### got.TimeoutError
1132
1133When the request is aborted due to a [timeout](#timeout). Includes an `event` and `timings` property.
1134
1135## Aborting the request
1136
1137The promise returned by Got has a [`.cancel()`](https://github.com/sindresorhus/p-cancelable) method which when called, aborts the request.
1138
1139```js
1140(async () => {
1141 const request = got(url, options);
1142
1143 // …
1144
1145 // In another part of the code
1146 if (something) {
1147 request.cancel();
1148 }
1149
1150 // …
1151
1152 try {
1153 await request;
1154 } catch (error) {
1155 if (request.isCanceled) { // Or `error instanceof got.CancelError`
1156 // Handle cancelation
1157 }
1158
1159 // Handle other errors
1160 }
1161})();
1162```
1163
1164When using hooks, simply throw an error to abort the request.
1165
1166```js
1167const got = require('got');
1168
1169(async () => {
1170 const request = got(url, {
1171 hooks: {
1172 beforeRequest: [
1173 () => {
1174 throw new Error('Oops. Request canceled.');
1175 }
1176 ]
1177 }
1178 });
1179
1180 try {
1181 await request;
1182 } catch (error) {
1183 // …
1184 }
1185})();
1186```
1187
1188<a name="cache-adapters"></a>
1189## Cache
1190
1191Got implements [RFC 7234](http://httpwg.org/specs/rfc7234.html) compliant HTTP caching which works out of the box in-memory and is easily pluggable with a wide range of storage adapters. Fresh cache entries are served directly from the cache, and stale cache entries are revalidated with `If-None-Match`/`If-Modified-Since` headers. You can read more about the underlying cache behavior in the [`cacheable-request` documentation](https://github.com/lukechilds/cacheable-request). For DNS cache, Got uses [`cacheable-lookup`](https://github.com/szmarczak/cacheable-lookup).
1192
1193You can use the JavaScript `Map` type as an in-memory cache:
1194
1195```js
1196const got = require('got');
1197
1198const map = new Map();
1199
1200(async () => {
1201 let response = await got('https://sindresorhus.com', {cache: map});
1202 console.log(response.isFromCache);
1203 //=> false
1204
1205 response = await got('https://sindresorhus.com', {cache: map});
1206 console.log(response.isFromCache);
1207 //=> true
1208})();
1209```
1210
1211Got uses [Keyv](https://github.com/lukechilds/keyv) internally to support a wide range of storage adapters. For something more scalable you could use an [official Keyv storage adapter](https://github.com/lukechilds/keyv#official-storage-adapters):
1212
1213```
1214$ npm install @keyv/redis
1215```
1216
1217```js
1218const got = require('got');
1219const KeyvRedis = require('@keyv/redis');
1220
1221const redis = new KeyvRedis('redis://user:pass@localhost:6379');
1222
1223got('https://sindresorhus.com', {cache: redis});
1224```
1225
1226Got supports anything that follows the Map API, so it's easy to write your own storage adapter or use a third-party solution.
1227
1228For example, the following are all valid storage adapters:
1229
1230```js
1231const storageAdapter = new Map();
1232// Or
1233const storageAdapter = require('./my-storage-adapter');
1234// Or
1235const QuickLRU = require('quick-lru');
1236const storageAdapter = new QuickLRU({maxSize: 1000});
1237
1238got('https://sindresorhus.com', {cache: storageAdapter});
1239```
1240
1241View the [Keyv docs](https://github.com/lukechilds/keyv) for more information on how to use storage adapters.
1242
1243## Proxies
1244
1245You can use the [`tunnel`](https://github.com/koichik/node-tunnel) package with the `agent` option to work with proxies:
1246
1247```js
1248const got = require('got');
1249const tunnel = require('tunnel');
1250
1251got('https://sindresorhus.com', {
1252 agent: tunnel.httpOverHttp({
1253 proxy: {
1254 host: 'localhost'
1255 }
1256 })
1257});
1258```
1259
1260Alternatively, use [`global-agent`](https://github.com/gajus/global-agent) to configure a global proxy for all HTTP/HTTPS traffic in your program.
1261
1262## Cookies
1263
1264You can use the [`tough-cookie`](https://github.com/salesforce/tough-cookie) package:
1265
1266```js
1267const {promisify} = require('util');
1268const got = require('got');
1269const {CookieJar} = require('tough-cookie');
1270
1271(async () => {
1272 const cookieJar = new CookieJar();
1273 const setCookie = promisify(cookieJar.setCookie.bind(cookieJar));
1274
1275 await setCookie('foo=bar', 'https://example.com');
1276 await got('https://example.com', {cookieJar});
1277})();
1278```
1279
1280## Form data
1281
1282You can use the [`form-data`](https://github.com/form-data/form-data) package to create POST request with form data:
1283
1284```js
1285const fs = require('fs');
1286const got = require('got');
1287const FormData = require('form-data');
1288
1289const form = new FormData();
1290
1291form.append('my_file', fs.createReadStream('/foo/bar.jpg'));
1292
1293got.post('https://example.com', {
1294 body: form
1295});
1296```
1297
1298## OAuth
1299
1300You can use the [`oauth-1.0a`](https://github.com/ddo/oauth-1.0a) package to create a signed OAuth request:
1301
1302```js
1303const got = require('got');
1304const crypto = require('crypto');
1305const OAuth = require('oauth-1.0a');
1306
1307const oauth = OAuth({
1308 consumer: {
1309 key: process.env.CONSUMER_KEY,
1310 secret: process.env.CONSUMER_SECRET
1311 },
1312 signature_method: 'HMAC-SHA1',
1313 hash_function: (baseString, key) => crypto.createHmac('sha1', key).update(baseString).digest('base64')
1314});
1315
1316const token = {
1317 key: process.env.ACCESS_TOKEN,
1318 secret: process.env.ACCESS_TOKEN_SECRET
1319};
1320
1321const url = 'https://api.twitter.com/1.1/statuses/home_timeline.json';
1322
1323got(url, {
1324 headers: oauth.toHeader(oauth.authorize({url, method: 'GET'}, token)),
1325 responseType: 'json'
1326});
1327```
1328
1329## Unix Domain Sockets
1330
1331Requests can also be sent via [unix domain sockets](http://serverfault.com/questions/124517/whats-the-difference-between-unix-socket-and-tcp-ip-socket). Use the following URL scheme: `PROTOCOL://unix:SOCKET:PATH`.
1332
1333- `PROTOCOL` - `http` or `https` *(optional)*
1334- `SOCKET` - Absolute path to a unix domain socket, for example: `/var/run/docker.sock`
1335- `PATH` - Request path, for example: `/v2/keys`
1336
1337```js
1338const got = require('got');
1339
1340got('http://unix:/var/run/docker.sock:/containers/json');
1341
1342// Or without protocol (HTTP by default)
1343got('unix:/var/run/docker.sock:/containers/json');
1344```
1345
1346## AWS
1347
1348Requests to AWS services need to have their headers signed. This can be accomplished by using the [`aws4`](https://www.npmjs.com/package/aws4) package. This is an example for querying an ["API Gateway"](https://docs.aws.amazon.com/apigateway/api-reference/signing-requests/) with a signed request.
1349
1350```js
1351const got = require('got');
1352const AWS = require('aws-sdk');
1353const aws4 = require('aws4');
1354
1355const chain = new AWS.CredentialProviderChain();
1356
1357// Create a Got instance to use relative paths and signed requests
1358const awsClient = got.extend({
1359 prefixUrl: 'https://<api-id>.execute-api.<api-region>.amazonaws.com/<stage>/',
1360 hooks: {
1361 beforeRequest: [
1362 async options => {
1363 const credentials = await chain.resolvePromise();
1364 aws4.sign(options, credentials);
1365 }
1366 ]
1367 }
1368});
1369
1370const response = await awsClient('endpoint/path', {
1371 // Request-specific options
1372});
1373```
1374
1375## Testing
1376
1377You can test your requests by using the [`nock`](https://github.com/node-nock/nock) package to mock an endpoint:
1378
1379```js
1380const got = require('got');
1381const nock = require('nock');
1382
1383nock('https://sindresorhus.com')
1384 .get('/')
1385 .reply(200, 'Hello world!');
1386
1387(async () => {
1388 const response = await got('https://sindresorhus.com');
1389 console.log(response.body);
1390 //=> 'Hello world!'
1391})();
1392```
1393
1394For real integration testing we recommend using [`ava`](https://github.com/avajs/ava) with [`create-test-server`](https://github.com/lukechilds/create-test-server). We're using a macro so we don't have to `server.listen()` and `server.close()` every test. Take a look at one of our tests:
1395
1396```js
1397test('retry function gets iteration count', withServer, async (t, server, got) => {
1398 let knocks = 0;
1399 server.get('/', (request, response) => {
1400 if (knocks++ === 1) {
1401 response.end('who`s there?');
1402 }
1403 });
1404
1405 await got({
1406 retry: {
1407 calculateDelay: ({attemptCount}) => {
1408 t.true(is.number(attemptCount));
1409 return attemptCount < 2 ? 1 : 0;
1410 }
1411 }
1412 });
1413});
1414```
1415
1416## Tips
1417
1418### JSON mode
1419
1420To pass an object as the body, you need to use the `json` option. It will be stringified using `JSON.stringify`. Example:
1421
1422```js
1423const got = require('got');
1424
1425(async () => {
1426 const {body} = await got.post('https://httpbin.org/anything', {
1427 json: {
1428 hello: 'world'
1429 },
1430 responseType: 'json'
1431 });
1432
1433 console.log(body.data);
1434 //=> '{"hello":"world"}'
1435})();
1436```
1437
1438To receive a JSON body you can either set `responseType` option to `json` or use `promise.json()`. Example:
1439
1440```js
1441const got = require('got');
1442
1443(async () => {
1444 const body = await got.post('https://httpbin.org/anything', {
1445 json: {
1446 hello: 'world'
1447 }
1448 }).json();
1449
1450 console.log(body);
1451 //=> {…}
1452})();
1453```
1454
1455### User Agent
1456
1457It's a good idea to set the `'user-agent'` header so the provider can more easily see how their resource is used. By default, it's the URL to this repo. You can omit this header by setting it to `undefined`.
1458
1459```js
1460const got = require('got');
1461const pkg = require('./package.json');
1462
1463got('https://sindresorhus.com', {
1464 headers: {
1465 'user-agent': `my-package/${pkg.version} (https://github.com/username/my-package)`
1466 }
1467});
1468
1469got('https://sindresorhus.com', {
1470 headers: {
1471 'user-agent': undefined
1472 }
1473});
1474```
1475
1476### 304 Responses
1477
1478Bear in mind; if you send an `if-modified-since` header and receive a `304 Not Modified` response, the body will be empty. It's your responsibility to cache and retrieve the body contents.
1479
1480### Custom endpoints
1481
1482Use `got.extend()` to make it nicer to work with REST APIs. Especially if you use the `prefixUrl` option.
1483
1484```js
1485const got = require('got');
1486const pkg = require('./package.json');
1487
1488const custom = got.extend({
1489 prefixUrl: 'example.com',
1490 responseType: 'json',
1491 headers: {
1492 'user-agent': `my-package/${pkg.version} (https://github.com/username/my-package)`
1493 }
1494});
1495
1496// Use `custom` exactly how you use `got`
1497(async () => {
1498 const list = await custom('v1/users/list');
1499})();
1500```
1501
1502### Experimental HTTP2 support
1503
1504Got provides an experimental support for HTTP2 using the [`http2-wrapper`](https://github.com/szmarczak/http2-wrapper) package:
1505
1506```js
1507const got = require('got');
1508const {request} = require('http2-wrapper');
1509
1510const h2got = got.extend({request});
1511
1512(async () => {
1513 const {body} = await h2got('https://nghttp2.org/httpbin/headers');
1514 console.log(body);
1515})();
1516```
1517
1518## FAQ
1519
1520### Why yet another HTTP client?
1521
1522Got was created because the popular [`request`](https://github.com/request/request) package is bloated: [![Install size](https://packagephobia.now.sh/badge?p=request)](https://packagephobia.now.sh/result?p=request)\
1523Furthermore, Got is fully written in TypeScript.
1524
1525### Electron support has been deprecated
1526
1527Some of the Got features may not work properly. See [#899](https://github.com/sindresorhus/got/issues/899) for more info.
1528
1529## Comparison
1530
1531| | `got` | [`request`][r0] | [`node-fetch`][n0] | [`ky`][k0] | [`axios`][a0] | [`superagent`][s0] |
1532|-----------------------|:------------------:|:------------------:|:--------------------:|:------------------------:|:------------------:|:----------------------:|
1533| HTTP/2 support | :grey_question: | :x: | :x: | :x: | :x: | :heavy_check_mark:\*\* |
1534| Browser support | :x: | :x: | :heavy_check_mark:\* | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
1535| Promise API | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
1536| Stream API | :heavy_check_mark: | :heavy_check_mark: | Node.js only | :x: | :x: | :heavy_check_mark: |
1537| Pagination API | :sparkle: | :x: | :x: | :x: | :x: | :x: |
1538| Request cancelation | :heavy_check_mark: | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
1539| RFC compliant caching | :heavy_check_mark: | :x: | :x: | :x: | :x: | :x: |
1540| Cookies (out-of-box) | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: | :x: | :x: |
1541| Follows redirects | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
1542| Retries on failure | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | :x: | :heavy_check_mark: |
1543| Progress events | :heavy_check_mark: | :x: | :x: | :heavy_check_mark:\*\*\* | Browser only | :heavy_check_mark: |
1544| Handles gzip/deflate | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
1545| Advanced timeouts | :heavy_check_mark: | :x: | :x: | :x: | :x: | :x: |
1546| Timings | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: | :x: | :x: |
1547| Errors with metadata | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | :x: |
1548| JSON mode | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
1549| Custom defaults | :heavy_check_mark: | :heavy_check_mark: | :x: | :heavy_check_mark: | :heavy_check_mark: | :x: |
1550| Composable | :heavy_check_mark: | :x: | :x: | :x: | :x: | :heavy_check_mark: |
1551| Hooks | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | :x: |
1552| Issues open | [![][gio]][g1] | [![][rio]][r1] | [![][nio]][n1] | [![][kio]][k1] | [![][aio]][a1] | [![][sio]][s1] |
1553| Issues closed | [![][gic]][g2] | [![][ric]][r2] | [![][nic]][n2] | [![][kic]][k2] | [![][aic]][a2] | [![][sic]][s2] |
1554| Downloads | [![][gd]][g3] | [![][rd]][r3] | [![][nd]][n3] | [![][kd]][k3] | [![][ad]][a3] | [![][sd]][s3] |
1555| Coverage | [![][gc]][g4] | [![][rc]][r4] | [![][nc]][n4] | [![][kc]][k4] | [![][ac]][a4] | [![][sc]][s4] |
1556| Build | [![][gb]][g5] | [![][rb]][r5] | [![][nb]][n5] | [![][kb]][k5] | [![][ab]][a5] | [![][sb]][s5] |
1557| Bugs | [![][gbg]][g6] | [![][rbg]][r6] | [![][nbg]][n6] | [![][kbg]][k6] | [![][abg]][a6] | [![][sbg]][s6] |
1558| Dependents | [![][gdp]][g7] | [![][rdp]][r7] | [![][ndp]][n7] | [![][kdp]][k7] | [![][adp]][a7] | [![][sdp]][s7] |
1559| Install size | [![][gis]][g8] | [![][ris]][r8] | [![][nis]][n8] | [![][kis]][k8] | [![][ais]][a8] | [![][sis]][s8] |
1560
1561\* It's almost API compatible with the browser `fetch` API.\
1562\*\* Need to switch the protocol manually. Doesn't accept PUSH streams and doesn't reuse HTTP/2 sessions.\
1563\*\*\* Currently, only `DownloadProgress` event is supported, `UploadProgress` event is not supported.\
1564:sparkle: Almost-stable feature, but the API may change. Don't hestitate to try it out!\
1565:grey_question: Feature in early stage of development. Very experimental.
1566
1567<!-- GITHUB -->
1568[k0]: https://github.com/sindresorhus/ky
1569[r0]: https://github.com/request/request
1570[n0]: https://github.com/bitinn/node-fetch
1571[a0]: https://github.com/axios/axios
1572[s0]: https://github.com/visionmedia/superagent
1573
1574<!-- ISSUES OPEN -->
1575[gio]: https://badgen.net/github/open-issues/sindresorhus/got?label
1576[kio]: https://badgen.net/github/open-issues/sindresorhus/ky?label
1577[rio]: https://badgen.net/github/open-issues/request/request?label
1578[nio]: https://badgen.net/github/open-issues/bitinn/node-fetch?label
1579[aio]: https://badgen.net/github/open-issues/axios/axios?label
1580[sio]: https://badgen.net/github/open-issues/visionmedia/superagent?label
1581
1582[g1]: https://github.com/sindresorhus/got/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc
1583[k1]: https://github.com/sindresorhus/ky/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc
1584[r1]: https://github.com/request/request/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc
1585[n1]: https://github.com/bitinn/node-fetch/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc
1586[a1]: https://github.com/axios/axios/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc
1587[s1]: https://github.com/visionmedia/superagent/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc
1588
1589<!-- ISSUES CLOSED -->
1590[gic]: https://badgen.net/github/closed-issues/sindresorhus/got?label
1591[kic]: https://badgen.net/github/closed-issues/sindresorhus/ky?label
1592[ric]: https://badgen.net/github/closed-issues/request/request?label
1593[nic]: https://badgen.net/github/closed-issues/bitinn/node-fetch?label
1594[aic]: https://badgen.net/github/closed-issues/axios/axios?label
1595[sic]: https://badgen.net/github/closed-issues/visionmedia/superagent?label
1596
1597[g2]: https://github.com/sindresorhus/got/issues?q=is%3Aissue+is%3Aclosed+sort%3Aupdated-desc
1598[k2]: https://github.com/sindresorhus/ky/issues?q=is%3Aissue+is%3Aclosed+sort%3Aupdated-desc
1599[r2]: https://github.com/request/request/issues?q=is%3Aissue+is%3Aclosed+sort%3Aupdated-desc
1600[n2]: https://github.com/bitinn/node-fetch/issues?q=is%3Aissue+is%3Aclosed+sort%3Aupdated-desc
1601[a2]: https://github.com/axios/axios/issues?q=is%3Aissue+is%3Aclosed+sort%3Aupdated-desc
1602[s2]: https://github.com/visionmedia/superagent/issues?q=is%3Aissue+is%3Aclosed+sort%3Aupdated-desc
1603
1604<!-- DOWNLOADS -->
1605[gd]: https://badgen.net/npm/dm/got?label
1606[kd]: https://badgen.net/npm/dm/ky?label
1607[rd]: https://badgen.net/npm/dm/request?label
1608[nd]: https://badgen.net/npm/dm/node-fetch?label
1609[ad]: https://badgen.net/npm/dm/axios?label
1610[sd]: https://badgen.net/npm/dm/superagent?label
1611
1612[g3]: https://www.npmjs.com/package/got
1613[k3]: https://www.npmjs.com/package/ky
1614[r3]: https://www.npmjs.com/package/request
1615[n3]: https://www.npmjs.com/package/node-fetch
1616[a3]: https://www.npmjs.com/package/axios
1617[s3]: https://www.npmjs.com/package/superagent
1618
1619<!-- COVERAGE -->
1620[gc]: https://badgen.net/coveralls/c/github/sindresorhus/got?label
1621[kc]: https://badgen.net/codecov/c/github/sindresorhus/ky?label
1622[rc]: https://badgen.net/coveralls/c/github/request/request?label
1623[nc]: https://badgen.net/coveralls/c/github/bitinn/node-fetch?label
1624[ac]: https://badgen.net/coveralls/c/github/mzabriskie/axios?label
1625[sc]: https://badgen.net/codecov/c/github/visionmedia/superagent?label
1626
1627[g4]: https://coveralls.io/github/sindresorhus/got
1628[k4]: https://codecov.io/gh/sindresorhus/ky
1629[r4]: https://coveralls.io/github/request/request
1630[n4]: https://coveralls.io/github/bitinn/node-fetch
1631[a4]: https://coveralls.io/github/mzabriskie/axios
1632[s4]: https://codecov.io/gh/visionmedia/superagent
1633
1634<!-- BUILD -->
1635[gb]: https://badgen.net/travis/sindresorhus/got?label
1636[kb]: https://badgen.net/travis/sindresorhus/ky?label
1637[rb]: https://badgen.net/travis/request/request?label
1638[nb]: https://badgen.net/travis/bitinn/node-fetch?label
1639[ab]: https://badgen.net/travis/axios/axios?label
1640[sb]: https://badgen.net/travis/visionmedia/superagent?label
1641
1642[g5]: https://travis-ci.org/sindresorhus/got
1643[k5]: https://travis-ci.org/sindresorhus/ky
1644[r5]: https://travis-ci.org/request/request
1645[n5]: https://travis-ci.org/bitinn/node-fetch
1646[a5]: https://travis-ci.org/axios/axios
1647[s5]: https://travis-ci.org/visionmedia/superagent
1648
1649<!-- BUGS -->
1650[gbg]: https://badgen.net/github/label-issues/sindresorhus/got/bug/open?label
1651[kbg]: https://badgen.net/github/label-issues/sindresorhus/ky/bug/open?label
1652[rbg]: https://badgen.net/github/label-issues/request/request/Needs%20investigation/open?label
1653[nbg]: https://badgen.net/github/label-issues/bitinn/node-fetch/bug/open?label
1654[abg]: https://badgen.net/github/label-issues/axios/axios/type:bug/open?label
1655[sbg]: https://badgen.net/github/label-issues/visionmedia/superagent/Bug/open?label
1656
1657[g6]: https://github.com/sindresorhus/got/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3Abug
1658[k6]: https://github.com/sindresorhus/ky/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3Abug
1659[r6]: https://github.com/request/request/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A"Needs+investigation"
1660[n6]: https://github.com/bitinn/node-fetch/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3Abug
1661[a6]: https://github.com/axios/axios/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3Atype:bug
1662[s6]: https://github.com/visionmedia/superagent/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3ABug
1663
1664<!-- DEPENDENTS -->
1665[gdp]: https://badgen.net/npm/dependents/got?label
1666[kdp]: https://badgen.net/npm/dependents/ky?label
1667[rdp]: https://badgen.net/npm/dependents/request?label
1668[ndp]: https://badgen.net/npm/dependents/node-fetch?label
1669[adp]: https://badgen.net/npm/dependents/axios?label
1670[sdp]: https://badgen.net/npm/dependents/superagent?label
1671
1672[g7]: https://www.npmjs.com/package/got?activeTab=dependents
1673[k7]: https://www.npmjs.com/package/ky?activeTab=dependents
1674[r7]: https://www.npmjs.com/package/request?activeTab=dependents
1675[n7]: https://www.npmjs.com/package/node-fetch?activeTab=dependents
1676[a7]: https://www.npmjs.com/package/axios?activeTab=dependents
1677[s7]: https://www.npmjs.com/package/visionmedia?activeTab=dependents
1678
1679<!-- INSTALL SIZE -->
1680[gis]: https://badgen.net/packagephobia/install/got?label
1681[kis]: https://badgen.net/packagephobia/install/ky?label
1682[ris]: https://badgen.net/packagephobia/install/request?label
1683[nis]: https://badgen.net/packagephobia/install/node-fetch?label
1684[ais]: https://badgen.net/packagephobia/install/axios?label
1685[sis]: https://badgen.net/packagephobia/install/superagent?label
1686
1687[g8]: https://packagephobia.now.sh/result?p=got
1688[k8]: https://packagephobia.now.sh/result?p=ky
1689[r8]: https://packagephobia.now.sh/result?p=request
1690[n8]: https://packagephobia.now.sh/result?p=node-fetch
1691[a8]: https://packagephobia.now.sh/result?p=axios
1692[s8]: https://packagephobia.now.sh/result?p=superagent
1693
1694[Click here][InstallSizeOfTheDependencies] to see the install size of the Got dependencies.
1695
1696[InstallSizeOfTheDependencies]: https://packagephobia.now.sh/result?p=@sindresorhus/is@1.0.0,@szmarczak/http-timer@3.1.0,@types/cacheable-request@6.0.1,cacheable-lookup@0.2.1,cacheable-request@7.0.0,decompress-response@5.0.0,duplexer3@0.1.4,get-stream@5.0.0,lowercase-keys@2.0.0,mimic-response@2.0.0,p-cancelable@2.0.0,responselike@2.0.0,to-readable-stream@2.0.0,type-fest@0.8.0
1697
1698## Related
1699
1700- [gh-got](https://github.com/sindresorhus/gh-got) - Got convenience wrapper to interact with the GitHub API
1701- [gl-got](https://github.com/singapore/gl-got) - Got convenience wrapper to interact with the GitLab API
1702- [travis-got](https://github.com/samverschueren/travis-got) - Got convenience wrapper to interact with the Travis API
1703- [graphql-got](https://github.com/kevva/graphql-got) - Got convenience wrapper to interact with GraphQL
1704- [GotQL](https://github.com/khaosdoctor/gotql) - Got convenience wrapper to interact with GraphQL using JSON-parsed queries instead of strings
1705- [got-fetch](https://github.com/alexghr/got-fetch) - Got with a `fetch` interface
1706
1707## Maintainers
1708
1709[![Sindre Sorhus](https://github.com/sindresorhus.png?size=100)](https://sindresorhus.com) | [![Szymon Marczak](https://github.com/szmarczak.png?size=100)](https://github.com/szmarczak)
1710---|---
1711[Sindre Sorhus](https://sindresorhus.com) | [Szymon Marczak](https://github.com/szmarczak)
1712
1713###### Former
1714
1715- [Vsevolod Strukchinsky](https://github.com/floatdrop)
1716- [Alexander Tesfamichael](https://github.com/alextes)
1717- [Brandon Smith](https://github.com/brandon93s)
1718- [Luke Childs](https://github.com/lukechilds)
1719
1720---
1721
1722<div align="center">
1723 <b>
1724 <a href="https://tidelift.com/subscription/pkg/npm-got?utm_source=npm-got&utm_medium=referral&utm_campaign=readme">Get professional support for this package with a Tidelift subscription</a>
1725 </b>
1726 <br>
1727 <sub>
1728 Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
1729 </sub>
1730</div>