UNPKG

61.1 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` unless the method is `GET` and the `allowGetBody` option is set to `true`.
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###### allowGetBody
417
418Type: `boolean`\
419Default: `false`
420
421**Note:** The [RFC 7321](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)**.
422
423Set this to `true` to allow sending body for the `GET` method. However, the [HTTP/2 specification](https://tools.ietf.org/html/rfc7540#section-8.1.3) says that `An HTTP GET request includes request header fields and no payload body`, therefore when using the HTTP/2 protocol this option will have no effect. This option is only meant to interact with non-compliant servers when you have no other choice.
424
425###### maxRedirects
426
427Type: `number`\
428Default: `10`
429
430If exceeded, the request will be aborted and a `MaxRedirectsError` will be thrown.
431
432###### decompress
433
434Type: `boolean`\
435Default: `true`
436
437Decompress 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.
438
439Brotli (`br`) support requires Node.js 11.7.0 or later.
440
441If 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.
442
443###### cache
444
445Type: `object`\
446Default: `false`
447
448[Cache adapter instance](#cache-adapters) for storing cached response data.
449
450###### dnsCache
451
452Type: `object`\
453Default: `false`
454
455[Cache adapter instance](#cache-adapters) for storing cached DNS data.
456
457###### request
458
459Type: `Function`\
460Default: `http.request | https.request` *(Depending on the protocol)*
461
462Custom request function. The main purpose of this is to [support HTTP2 using a wrapper](#experimental-http2-support).
463
464###### useElectronNet
465
466Type: `boolean`\
467Default: `false`
468
469[**Deprecated**](https://github.com/sindresorhus/got#electron-support-has-been-deprecated)
470
471When 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).
472
473###### throwHttpErrors
474
475Type: `boolean`\
476Default: `true`
477
478Determines if a `got.HTTPError` is thrown for error responses (non-2xx status codes).
479
480If 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.
481
482###### agent
483
484Same as the [`agent` option](https://nodejs.org/api/http.html#http_http_request_url_options_callback) for `http.request`, but with an extra feature:
485
486If 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.
487
488```js
489const got = require('got');
490const HttpAgent = require('agentkeepalive');
491const {HttpsAgent} = HttpAgent;
492
493got('https://sindresorhus.com', {
494 agent: {
495 http: new HttpAgent(),
496 https: new HttpsAgent()
497 }
498});
499```
500
501###### hooks
502
503Type: `object<string, Function[]>`
504
505Hooks allow modifications during the request lifecycle. Hook functions may be async and are run serially.
506
507###### hooks.init
508
509Type: `Function[]`\
510Default: `[]`
511
512Called 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.
513
514See the [Request migration guide](documentation/migration-guides.md#breaking-changes) for an example.
515
516**Note:** This hook must be synchronous!
517
518###### hooks.beforeRequest
519
520Type: `Function[]`\
521Default: `[]`
522
523Called 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.
524
525See the [AWS section](#aws) for an example.
526
527###### hooks.beforeRedirect
528
529Type: `Function[]`\
530Default: `[]`
531
532Called 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:
533
534```js
535const got = require('got');
536
537got('https://example.com', {
538 hooks: {
539 beforeRedirect: [
540 (options, response) => {
541 if (options.hostname === 'deadSite') {
542 options.hostname = 'fallbackSite';
543 }
544 }
545 ]
546 }
547});
548```
549
550###### hooks.beforeRetry
551
552Type: `Function[]`\
553Default: `[]`
554
555**Note:** When using streams, this hook is ignored.
556
557Called 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:
558
559```js
560const got = require('got');
561
562got.post('https://example.com', {
563 hooks: {
564 beforeRetry: [
565 (options, error, retryCount) => {
566 if (error.statusCode === 413) { // Payload too large
567 options.body = getNewBody();
568 }
569 }
570 ]
571 }
572});
573```
574
575**Note:** When retrying in a `afterResponse` hook, all remaining `beforeRetry` hooks will be called without the `error` and `retryCount` arguments.
576
577###### hooks.afterResponse
578
579Type: `Function[]`\
580Default: `[]`
581
582**Note:** When using streams, this hook is ignored.
583
584Called with [response object](#response) and a retry function. Calling the retry function will trigger `beforeRetry` hooks.
585
586Each function should return the response. This is especially useful when you want to refresh an access token. Example:
587
588```js
589const got = require('got');
590
591const instance = got.extend({
592 hooks: {
593 afterResponse: [
594 (response, retryWithMergedOptions) => {
595 if (response.statusCode === 401) { // Unauthorized
596 const updatedOptions = {
597 headers: {
598 token: getNewToken() // Refresh the access token
599 }
600 };
601
602 // Save for further requests
603 instance.defaults.options = got.mergeOptions(instance.defaults.options, updatedOptions);
604
605 // Make a new retry
606 return retryWithMergedOptions(updatedOptions);
607 }
608
609 // No changes otherwise
610 return response;
611 }
612 ],
613 beforeRetry: [
614 (options, error, retryCount) => {
615 // This will be called on `retryWithMergedOptions(...)`
616 }
617 ]
618 },
619 mutableDefaults: true
620});
621```
622
623###### hooks.beforeError
624
625Type: `Function[]`\
626Default: `[]`
627
628Called 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.
629
630**Note:** Errors thrown while normalizing input options are thrown directly and not part of this hook.
631
632```js
633const got = require('got');
634
635got('https://api.github.com/some-endpoint', {
636 hooks: {
637 beforeError: [
638 error => {
639 const {response} = error;
640 if (response && response.body) {
641 error.name = 'GitHubError';
642 error.message = `${response.body.message} (${error.statusCode})`;
643 }
644
645 return error;
646 }
647 ]
648 }
649});
650```
651
652##### \_pagination
653
654Type: `object`
655
656**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.
657
658###### \_pagination.transform
659
660Type: `Function`\
661Default: `response => JSON.parse(response.body)`
662
663A function that transform [`Response`](#response) into an array of items. This is where you should do the parsing.
664
665###### \_pagination.paginate
666
667Type: `Function`\
668Default: [`Link` header logic](source/index.ts)
669
670A function that returns an object representing Got options pointing to the next page. If there are no more pages, `false` should be returned.
671
672###### \_pagination.filter
673
674Type: `Function`\
675Default: `(item, allItems) => true`
676
677Checks whether the item should be emitted or not.
678
679###### \_pagination.shouldContinue
680
681Type: `Function`\
682Default: `(item, allItems) => true`
683
684Checks whether the pagination should continue.
685
686For 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.
687
688###### \_pagination.countLimit
689
690Type: `number`\
691Default: `Infinity`
692
693The maximum amount of items that should be emitted.
694
695#### Response
696
697The 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.
698
699##### request
700
701Type: `object`
702
703**Note:** This is not a [http.ClientRequest](https://nodejs.org/api/http.html#http_class_http_clientrequest).
704
705- `options` - The Got options that were set on this request.
706
707##### body
708
709Type: `string | object | Buffer` *(Depending on `options.responseType`)*
710
711The result of the request.
712
713##### url
714
715Type: `string`
716
717The request URL or the final URL after redirects.
718
719##### ip
720
721Type: `string`
722
723The remote IP address.
724
725**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).
726
727##### requestUrl
728
729Type: `string`
730
731The original request URL.
732
733##### timings
734
735Type: `object`
736
737The object contains the following properties:
738
739- `start` - Time when the request started.
740- `socket` - Time when a socket was assigned to the request.
741- `lookup` - Time when the DNS lookup finished.
742- `connect` - Time when the socket successfully connected.
743- `secureConnect` - Time when the socket securely connected.
744- `upload` - Time when the request finished uploading.
745- `response` - Time when the request fired `response` event.
746- `end` - Time when the response fired `end` event.
747- `error` - Time when the request fired `error` event.
748- `abort` - Time when the request fired `abort` event.
749- `phases`
750 - `wait` - `timings.socket - timings.start`
751 - `dns` - `timings.lookup - timings.socket`
752 - `tcp` - `timings.connect - timings.lookup`
753 - `tls` - `timings.secureConnect - timings.connect`
754 - `request` - `timings.upload - (timings.secureConnect || timings.connect)`
755 - `firstByte` - `timings.response - timings.upload`
756 - `download` - `timings.end - timings.response`
757 - `total` - `(timings.end || timings.error || timings.abort) - timings.start`
758
759If something has not been measured yet, it will be `undefined`.
760
761**Note:** The time is a `number` representing the milliseconds elapsed since the UNIX epoch.
762
763##### isFromCache
764
765Type: `boolean`
766
767Whether the response was retrieved from the cache.
768
769##### redirectUrls
770
771Type: `string[]`
772
773The redirect URLs.
774
775##### retryCount
776
777Type: `number`
778
779The number of times the request was retried.
780
781#### Streams
782
783**Note:** Progress events, redirect events and request/response events can also be used with promises.
784
785**Note:** To access `response.isFromCache` you need to use `got.stream(url, options).isFromCache`. The value will be undefined until the `response` event.
786
787#### got.stream(url, options?)
788
789Sets `options.isStream` to `true`.
790
791Returns a [duplex stream](https://nodejs.org/api/stream.html#stream_class_stream_duplex) with additional events:
792
793##### .on('request', request)
794
795`request` event to get the request object of the request.
796
797**Tip:** You can use `request` event to abort request:
798
799```js
800got.stream('https://github.com')
801 .on('request', request => setTimeout(() => request.abort(), 50));
802```
803
804##### .on('response', response)
805
806The `response` event to get the response object of the final request.
807
808##### .on('redirect', response, nextOptions)
809
810The `redirect` event to get the response object of a redirect. The second argument is options for the next request to the redirect location.
811
812##### .on('uploadProgress', progress)
813##### .on('downloadProgress', progress)
814
815Progress events for uploading (sending a request) and downloading (receiving a response). The `progress` argument is an object like:
816
817```js
818{
819 percent: 0.1,
820 transferred: 1024,
821 total: 10240
822}
823```
824
825If the `content-length` header is missing, `total` will be `undefined`.
826
827```js
828(async () => {
829 const response = await got('https://sindresorhus.com')
830 .on('downloadProgress', progress => {
831 // Report download progress
832 })
833 .on('uploadProgress', progress => {
834 // Report upload progress
835 });
836
837 console.log(response);
838})();
839```
840
841##### .on('error', error, body, response)
842
843The `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.
844
845#### Pagination
846
847#### got.paginate(url, options?)
848
849Returns an async iterator:
850
851```js
852(async () => {
853 const countLimit = 10;
854
855 const pagination = got.paginate('https://api.github.com/repos/sindresorhus/got/commits', {
856 _pagination: {countLimit}
857 });
858
859 console.log(`Printing latest ${countLimit} Got commits (newest to oldest):`);
860
861 for await (const commitData of pagination) {
862 console.log(commitData.commit.message);
863 }
864})();
865```
866
867See [`options._pagination`](#_pagination) for more pagination options.
868
869#### got.get(url, options?)
870#### got.post(url, options?)
871#### got.put(url, options?)
872#### got.patch(url, options?)
873#### got.head(url, options?)
874#### got.delete(url, options?)
875
876Sets `options.method` to the method name and makes a request.
877
878### Instances
879
880#### got.extend(...options)
881
882Configure 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.
883
884```js
885const client = got.extend({
886 prefixUrl: 'https://example.com',
887 headers: {
888 'x-unicorn': 'rainbow'
889 }
890});
891
892client.get('demo');
893
894/* HTTP Request =>
895 * GET /demo HTTP/1.1
896 * Host: example.com
897 * x-unicorn: rainbow
898 */
899```
900
901```js
902(async () => {
903 const client = got.extend({
904 prefixUrl: 'httpbin.org',
905 headers: {
906 'x-foo': 'bar'
907 }
908 });
909 const {headers} = await client.get('headers').json();
910 //=> headers['x-foo'] === 'bar'
911
912 const jsonClient = client.extend({
913 responseType: 'json',
914 resolveBodyOnly: true,
915 headers: {
916 'x-baz': 'qux'
917 }
918 });
919 const {headers: headers2} = await jsonClient.get('headers');
920 //=> headers2['x-foo'] === 'bar'
921 //=> headers2['x-baz'] === 'qux'
922})();
923```
924
925Additionally, `got.extend()` accepts two properties from the `defaults` object: `mutableDefaults` and `handlers`. Example:
926
927```js
928// You can now modify `mutableGot.defaults.options`.
929const mutableGot = got.extend({mutableDefaults: true});
930
931const mergedHandlers = got.extend({
932 handlers: [
933 (options, next) => {
934 options.getHeader('referer');
935
936 return next(options);
937 }
938 ]
939});
940```
941
942**Note:** Handlers can be asynchronous. The recommended approach is:
943
944```js
945const handler = (options, next) => {
946 if (options.stream) {
947 // It's a Stream
948 return next(options);
949 }
950
951 // It's a Promise
952 return (async () => {
953 try {
954 const response = await next(options);
955 response.yourOwnProperty = true;
956 return response;
957 } catch (error) {
958 // Every error will be replaced by this one.
959 // Before you receive any error here,
960 // it will be passed to the `beforeError` hooks first.
961 // Note: this one won't be passed to `beforeError` hook. It's final.
962 throw new Error('Your very own error.');
963 }
964 })();
965};
966
967const instance = got.extend({handlers: [handler]});
968```
969
970#### got.extend(...instances)
971
972Merges many instances into a single one:
973- options are merged using [`got.mergeOptions()`](#gotmergeoptionsparentoptions-newoptions) (+ hooks are merged too),
974- handlers are stored in an array (you can access them through `instance.defaults.handlers`).
975
976#### got.extend(...options, ...instances, ...)
977
978It's possible to combine options and instances.\
979It gives the same effect as `got.extend(...options).extend(...instances)`:
980
981```js
982const a = {headers: {cat: 'meow'}};
983const b = got.extend({
984 options: {
985 headers: {
986 cow: 'moo'
987 }
988 }
989});
990
991// The same as `got.extend(a).extend(b)`.
992// Note `a` is options and `b` is an instance.
993got.extend(a, b);
994//=> {headers: {cat: 'meow', cow: 'moo'}}
995```
996
997#### got.mergeOptions(parentOptions, newOptions)
998
999Extends 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:
1000
1001```js
1002const a = {headers: {cat: 'meow', wolf: ['bark', 'wrrr']}};
1003const b = {headers: {cow: 'moo', wolf: ['auuu']}};
1004
1005{...a, ...b} // => {headers: {cow: 'moo', wolf: ['auuu']}}
1006got.mergeOptions(a, b) // => {headers: {cat: 'meow', cow: 'moo', wolf: ['auuu']}}
1007```
1008
1009Options are deeply merged to a new object. The value of each key is determined as follows:
1010
1011- If the new property is set to `undefined`, it keeps the old one.
1012- 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).
1013- 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).
1014- If the new property is a plain `object`:
1015 - If the parent property is a plain `object` too, both values are merged recursively into a new `object`.
1016 - Otherwise, only the new value is deeply cloned.
1017- If the new property is an `Array`, it overwrites the old one with a deep clone of the new property.
1018- Otherwise, the new value is assigned to the key.
1019
1020#### got.defaults
1021
1022Type: `object`
1023
1024The Got defaults used in that instance.
1025
1026##### [options](#options)
1027
1028##### handlers
1029
1030Type: `Function[]`\
1031Default: `[]`
1032
1033An 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.
1034
1035Each handler takes two arguments:
1036
1037###### [options](#options)
1038
1039###### next()
1040
1041Returns a `Promise` or a `Stream` depending on [`options.isStream`](#isstream).
1042
1043```js
1044const settings = {
1045 handlers: [
1046 (options, next) => {
1047 if (options.isStream) {
1048 // It's a Stream, so we can perform stream-specific actions on it
1049 return next(options)
1050 .on('request', request => {
1051 setTimeout(() => {
1052 request.abort();
1053 }, 50);
1054 });
1055 }
1056
1057 // It's a Promise
1058 return next(options);
1059 }
1060 ],
1061 options: got.mergeOptions(got.defaults.options, {
1062 responseType: 'json'
1063 })
1064};
1065
1066const jsonGot = got.extend(settings);
1067```
1068
1069##### mutableDefaults
1070
1071Type: `boolean`\
1072Default: `false`
1073
1074A 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.
1075
1076## Types
1077
1078Got exports some handy TypeScript types and interfaces. See the type definition for all the exported types.
1079
1080### Got
1081
1082TypeScript 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.
1083
1084```ts
1085import {GotRequestMethod} from 'got';
1086
1087interface Dependencies {
1088 readonly post: GotRequestMethod
1089}
1090```
1091
1092### Hooks
1093
1094When writing hooks, you can refer to their types to keep your interfaces consistent.
1095
1096```ts
1097import {BeforeRequestHook} from 'got';
1098
1099const addAccessToken = (accessToken: string): BeforeRequestHook => options => {
1100 options.path = `${options.path}?access_token=${accessToken}`;
1101}
1102```
1103
1104## Errors
1105
1106Each error contains an `options` property which are the options Got used to create a request - just to make debugging easier.
1107
1108#### got.CacheError
1109
1110When a cache method fails, for example, if the database goes down or there's a filesystem error.
1111
1112#### got.RequestError
1113
1114When a request fails. Contains a `code` property with error class code, like `ECONNREFUSED`.
1115
1116#### got.ReadError
1117
1118When reading from response stream fails.
1119
1120#### got.ParseError
1121
1122When server response code is 2xx, and parsing body fails. Includes a `response` property.
1123
1124#### got.HTTPError
1125
1126When the server response code is not 2xx. Includes a `response` property.
1127
1128#### got.MaxRedirectsError
1129
1130When the server redirects you more than ten times. Includes a `response` property.
1131
1132#### got.UnsupportedProtocolError
1133
1134When given an unsupported protocol.
1135
1136#### got.CancelError
1137
1138When the request is aborted with `.cancel()`.
1139
1140#### got.TimeoutError
1141
1142When the request is aborted due to a [timeout](#timeout). Includes an `event` and `timings` property.
1143
1144## Aborting the request
1145
1146The promise returned by Got has a [`.cancel()`](https://github.com/sindresorhus/p-cancelable) method which when called, aborts the request.
1147
1148```js
1149(async () => {
1150 const request = got(url, options);
1151
1152 // …
1153
1154 // In another part of the code
1155 if (something) {
1156 request.cancel();
1157 }
1158
1159 // …
1160
1161 try {
1162 await request;
1163 } catch (error) {
1164 if (request.isCanceled) { // Or `error instanceof got.CancelError`
1165 // Handle cancelation
1166 }
1167
1168 // Handle other errors
1169 }
1170})();
1171```
1172
1173When using hooks, simply throw an error to abort the request.
1174
1175```js
1176const got = require('got');
1177
1178(async () => {
1179 const request = got(url, {
1180 hooks: {
1181 beforeRequest: [
1182 () => {
1183 throw new Error('Oops. Request canceled.');
1184 }
1185 ]
1186 }
1187 });
1188
1189 try {
1190 await request;
1191 } catch (error) {
1192 // …
1193 }
1194})();
1195```
1196
1197<a name="cache-adapters"></a>
1198## Cache
1199
1200Got 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).
1201
1202You can use the JavaScript `Map` type as an in-memory cache:
1203
1204```js
1205const got = require('got');
1206
1207const map = new Map();
1208
1209(async () => {
1210 let response = await got('https://sindresorhus.com', {cache: map});
1211 console.log(response.isFromCache);
1212 //=> false
1213
1214 response = await got('https://sindresorhus.com', {cache: map});
1215 console.log(response.isFromCache);
1216 //=> true
1217})();
1218```
1219
1220Got 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):
1221
1222```
1223$ npm install @keyv/redis
1224```
1225
1226```js
1227const got = require('got');
1228const KeyvRedis = require('@keyv/redis');
1229
1230const redis = new KeyvRedis('redis://user:pass@localhost:6379');
1231
1232got('https://sindresorhus.com', {cache: redis});
1233```
1234
1235Got supports anything that follows the Map API, so it's easy to write your own storage adapter or use a third-party solution.
1236
1237For example, the following are all valid storage adapters:
1238
1239```js
1240const storageAdapter = new Map();
1241// Or
1242const storageAdapter = require('./my-storage-adapter');
1243// Or
1244const QuickLRU = require('quick-lru');
1245const storageAdapter = new QuickLRU({maxSize: 1000});
1246
1247got('https://sindresorhus.com', {cache: storageAdapter});
1248```
1249
1250View the [Keyv docs](https://github.com/lukechilds/keyv) for more information on how to use storage adapters.
1251
1252## Proxies
1253
1254You can use the [`tunnel`](https://github.com/koichik/node-tunnel) package with the `agent` option to work with proxies:
1255
1256```js
1257const got = require('got');
1258const tunnel = require('tunnel');
1259
1260got('https://sindresorhus.com', {
1261 agent: tunnel.httpOverHttp({
1262 proxy: {
1263 host: 'localhost'
1264 }
1265 })
1266});
1267```
1268
1269Alternatively, use [`global-agent`](https://github.com/gajus/global-agent) to configure a global proxy for all HTTP/HTTPS traffic in your program.
1270
1271## Cookies
1272
1273You can use the [`tough-cookie`](https://github.com/salesforce/tough-cookie) package:
1274
1275```js
1276const {promisify} = require('util');
1277const got = require('got');
1278const {CookieJar} = require('tough-cookie');
1279
1280(async () => {
1281 const cookieJar = new CookieJar();
1282 const setCookie = promisify(cookieJar.setCookie.bind(cookieJar));
1283
1284 await setCookie('foo=bar', 'https://example.com');
1285 await got('https://example.com', {cookieJar});
1286})();
1287```
1288
1289## Form data
1290
1291You can use the [`form-data`](https://github.com/form-data/form-data) package to create POST request with form data:
1292
1293```js
1294const fs = require('fs');
1295const got = require('got');
1296const FormData = require('form-data');
1297
1298const form = new FormData();
1299
1300form.append('my_file', fs.createReadStream('/foo/bar.jpg'));
1301
1302got.post('https://example.com', {
1303 body: form
1304});
1305```
1306
1307## OAuth
1308
1309You can use the [`oauth-1.0a`](https://github.com/ddo/oauth-1.0a) package to create a signed OAuth request:
1310
1311```js
1312const got = require('got');
1313const crypto = require('crypto');
1314const OAuth = require('oauth-1.0a');
1315
1316const oauth = OAuth({
1317 consumer: {
1318 key: process.env.CONSUMER_KEY,
1319 secret: process.env.CONSUMER_SECRET
1320 },
1321 signature_method: 'HMAC-SHA1',
1322 hash_function: (baseString, key) => crypto.createHmac('sha1', key).update(baseString).digest('base64')
1323});
1324
1325const token = {
1326 key: process.env.ACCESS_TOKEN,
1327 secret: process.env.ACCESS_TOKEN_SECRET
1328};
1329
1330const url = 'https://api.twitter.com/1.1/statuses/home_timeline.json';
1331
1332got(url, {
1333 headers: oauth.toHeader(oauth.authorize({url, method: 'GET'}, token)),
1334 responseType: 'json'
1335});
1336```
1337
1338## Unix Domain Sockets
1339
1340Requests 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`.
1341
1342- `PROTOCOL` - `http` or `https` *(optional)*
1343- `SOCKET` - Absolute path to a unix domain socket, for example: `/var/run/docker.sock`
1344- `PATH` - Request path, for example: `/v2/keys`
1345
1346```js
1347const got = require('got');
1348
1349got('http://unix:/var/run/docker.sock:/containers/json');
1350
1351// Or without protocol (HTTP by default)
1352got('unix:/var/run/docker.sock:/containers/json');
1353```
1354
1355## AWS
1356
1357Requests 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.
1358
1359```js
1360const got = require('got');
1361const AWS = require('aws-sdk');
1362const aws4 = require('aws4');
1363
1364const chain = new AWS.CredentialProviderChain();
1365
1366// Create a Got instance to use relative paths and signed requests
1367const awsClient = got.extend({
1368 prefixUrl: 'https://<api-id>.execute-api.<api-region>.amazonaws.com/<stage>/',
1369 hooks: {
1370 beforeRequest: [
1371 async options => {
1372 const credentials = await chain.resolvePromise();
1373 aws4.sign(options, credentials);
1374 }
1375 ]
1376 }
1377});
1378
1379const response = await awsClient('endpoint/path', {
1380 // Request-specific options
1381});
1382```
1383
1384## Testing
1385
1386You can test your requests by using the [`nock`](https://github.com/node-nock/nock) package to mock an endpoint:
1387
1388```js
1389const got = require('got');
1390const nock = require('nock');
1391
1392nock('https://sindresorhus.com')
1393 .get('/')
1394 .reply(200, 'Hello world!');
1395
1396(async () => {
1397 const response = await got('https://sindresorhus.com');
1398 console.log(response.body);
1399 //=> 'Hello world!'
1400})();
1401```
1402
1403For 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:
1404
1405```js
1406test('retry function gets iteration count', withServer, async (t, server, got) => {
1407 let knocks = 0;
1408 server.get('/', (request, response) => {
1409 if (knocks++ === 1) {
1410 response.end('who`s there?');
1411 }
1412 });
1413
1414 await got({
1415 retry: {
1416 calculateDelay: ({attemptCount}) => {
1417 t.true(is.number(attemptCount));
1418 return attemptCount < 2 ? 1 : 0;
1419 }
1420 }
1421 });
1422});
1423```
1424
1425## Tips
1426
1427### JSON mode
1428
1429To pass an object as the body, you need to use the `json` option. It will be stringified using `JSON.stringify`. Example:
1430
1431```js
1432const got = require('got');
1433
1434(async () => {
1435 const {body} = await got.post('https://httpbin.org/anything', {
1436 json: {
1437 hello: 'world'
1438 },
1439 responseType: 'json'
1440 });
1441
1442 console.log(body.data);
1443 //=> '{"hello":"world"}'
1444})();
1445```
1446
1447To receive a JSON body you can either set `responseType` option to `json` or use `promise.json()`. Example:
1448
1449```js
1450const got = require('got');
1451
1452(async () => {
1453 const body = await got.post('https://httpbin.org/anything', {
1454 json: {
1455 hello: 'world'
1456 }
1457 }).json();
1458
1459 console.log(body);
1460 //=> {…}
1461})();
1462```
1463
1464### User Agent
1465
1466It'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`.
1467
1468```js
1469const got = require('got');
1470const pkg = require('./package.json');
1471
1472got('https://sindresorhus.com', {
1473 headers: {
1474 'user-agent': `my-package/${pkg.version} (https://github.com/username/my-package)`
1475 }
1476});
1477
1478got('https://sindresorhus.com', {
1479 headers: {
1480 'user-agent': undefined
1481 }
1482});
1483```
1484
1485### 304 Responses
1486
1487Bear 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.
1488
1489### Custom endpoints
1490
1491Use `got.extend()` to make it nicer to work with REST APIs. Especially if you use the `prefixUrl` option.
1492
1493```js
1494const got = require('got');
1495const pkg = require('./package.json');
1496
1497const custom = got.extend({
1498 prefixUrl: 'example.com',
1499 responseType: 'json',
1500 headers: {
1501 'user-agent': `my-package/${pkg.version} (https://github.com/username/my-package)`
1502 }
1503});
1504
1505// Use `custom` exactly how you use `got`
1506(async () => {
1507 const list = await custom('v1/users/list');
1508})();
1509```
1510
1511### Experimental HTTP2 support
1512
1513Got provides an experimental support for HTTP2 using the [`http2-wrapper`](https://github.com/szmarczak/http2-wrapper) package:
1514
1515```js
1516const got = require('got');
1517const {request} = require('http2-wrapper');
1518
1519const h2got = got.extend({request});
1520
1521(async () => {
1522 const {body} = await h2got('https://nghttp2.org/httpbin/headers');
1523 console.log(body);
1524})();
1525```
1526
1527## FAQ
1528
1529### Why yet another HTTP client?
1530
1531Got 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)\
1532Furthermore, Got is fully written in TypeScript.
1533
1534### Electron support has been deprecated
1535
1536Some of the Got features may not work properly. See [#899](https://github.com/sindresorhus/got/issues/899) for more info.
1537
1538## Comparison
1539
1540| | `got` | [`request`][r0] | [`node-fetch`][n0] | [`ky`][k0] | [`axios`][a0] | [`superagent`][s0] |
1541|-----------------------|:------------------:|:------------------:|:--------------------:|:------------------------:|:------------------:|:----------------------:|
1542| HTTP/2 support | :grey_question: | :x: | :x: | :x: | :x: | :heavy_check_mark:\*\* |
1543| Browser support | :x: | :x: | :heavy_check_mark:\* | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
1544| Promise API | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
1545| Stream API | :heavy_check_mark: | :heavy_check_mark: | Node.js only | :x: | :x: | :heavy_check_mark: |
1546| Pagination API | :sparkle: | :x: | :x: | :x: | :x: | :x: |
1547| Request cancelation | :heavy_check_mark: | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
1548| RFC compliant caching | :heavy_check_mark: | :x: | :x: | :x: | :x: | :x: |
1549| Cookies (out-of-box) | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: | :x: | :x: |
1550| Follows redirects | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
1551| Retries on failure | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | :x: | :heavy_check_mark: |
1552| Progress events | :heavy_check_mark: | :x: | :x: | :heavy_check_mark:\*\*\* | Browser only | :heavy_check_mark: |
1553| Handles gzip/deflate | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
1554| Advanced timeouts | :heavy_check_mark: | :x: | :x: | :x: | :x: | :x: |
1555| Timings | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: | :x: | :x: |
1556| Errors with metadata | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | :x: |
1557| JSON mode | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
1558| Custom defaults | :heavy_check_mark: | :heavy_check_mark: | :x: | :heavy_check_mark: | :heavy_check_mark: | :x: |
1559| Composable | :heavy_check_mark: | :x: | :x: | :x: | :x: | :heavy_check_mark: |
1560| Hooks | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | :x: |
1561| Issues open | [![][gio]][g1] | [![][rio]][r1] | [![][nio]][n1] | [![][kio]][k1] | [![][aio]][a1] | [![][sio]][s1] |
1562| Issues closed | [![][gic]][g2] | [![][ric]][r2] | [![][nic]][n2] | [![][kic]][k2] | [![][aic]][a2] | [![][sic]][s2] |
1563| Downloads | [![][gd]][g3] | [![][rd]][r3] | [![][nd]][n3] | [![][kd]][k3] | [![][ad]][a3] | [![][sd]][s3] |
1564| Coverage | [![][gc]][g4] | [![][rc]][r4] | [![][nc]][n4] | [![][kc]][k4] | [![][ac]][a4] | [![][sc]][s4] |
1565| Build | [![][gb]][g5] | [![][rb]][r5] | [![][nb]][n5] | [![][kb]][k5] | [![][ab]][a5] | [![][sb]][s5] |
1566| Bugs | [![][gbg]][g6] | [![][rbg]][r6] | [![][nbg]][n6] | [![][kbg]][k6] | [![][abg]][a6] | [![][sbg]][s6] |
1567| Dependents | [![][gdp]][g7] | [![][rdp]][r7] | [![][ndp]][n7] | [![][kdp]][k7] | [![][adp]][a7] | [![][sdp]][s7] |
1568| Install size | [![][gis]][g8] | [![][ris]][r8] | [![][nis]][n8] | [![][kis]][k8] | [![][ais]][a8] | [![][sis]][s8] |
1569
1570\* It's almost API compatible with the browser `fetch` API.\
1571\*\* Need to switch the protocol manually. Doesn't accept PUSH streams and doesn't reuse HTTP/2 sessions.\
1572\*\*\* Currently, only `DownloadProgress` event is supported, `UploadProgress` event is not supported.\
1573:sparkle: Almost-stable feature, but the API may change. Don't hestitate to try it out!\
1574:grey_question: Feature in early stage of development. Very experimental.
1575
1576<!-- GITHUB -->
1577[k0]: https://github.com/sindresorhus/ky
1578[r0]: https://github.com/request/request
1579[n0]: https://github.com/bitinn/node-fetch
1580[a0]: https://github.com/axios/axios
1581[s0]: https://github.com/visionmedia/superagent
1582
1583<!-- ISSUES OPEN -->
1584[gio]: https://badgen.net/github/open-issues/sindresorhus/got?label
1585[kio]: https://badgen.net/github/open-issues/sindresorhus/ky?label
1586[rio]: https://badgen.net/github/open-issues/request/request?label
1587[nio]: https://badgen.net/github/open-issues/bitinn/node-fetch?label
1588[aio]: https://badgen.net/github/open-issues/axios/axios?label
1589[sio]: https://badgen.net/github/open-issues/visionmedia/superagent?label
1590
1591[g1]: https://github.com/sindresorhus/got/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc
1592[k1]: https://github.com/sindresorhus/ky/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc
1593[r1]: https://github.com/request/request/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc
1594[n1]: https://github.com/bitinn/node-fetch/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc
1595[a1]: https://github.com/axios/axios/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc
1596[s1]: https://github.com/visionmedia/superagent/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc
1597
1598<!-- ISSUES CLOSED -->
1599[gic]: https://badgen.net/github/closed-issues/sindresorhus/got?label
1600[kic]: https://badgen.net/github/closed-issues/sindresorhus/ky?label
1601[ric]: https://badgen.net/github/closed-issues/request/request?label
1602[nic]: https://badgen.net/github/closed-issues/bitinn/node-fetch?label
1603[aic]: https://badgen.net/github/closed-issues/axios/axios?label
1604[sic]: https://badgen.net/github/closed-issues/visionmedia/superagent?label
1605
1606[g2]: https://github.com/sindresorhus/got/issues?q=is%3Aissue+is%3Aclosed+sort%3Aupdated-desc
1607[k2]: https://github.com/sindresorhus/ky/issues?q=is%3Aissue+is%3Aclosed+sort%3Aupdated-desc
1608[r2]: https://github.com/request/request/issues?q=is%3Aissue+is%3Aclosed+sort%3Aupdated-desc
1609[n2]: https://github.com/bitinn/node-fetch/issues?q=is%3Aissue+is%3Aclosed+sort%3Aupdated-desc
1610[a2]: https://github.com/axios/axios/issues?q=is%3Aissue+is%3Aclosed+sort%3Aupdated-desc
1611[s2]: https://github.com/visionmedia/superagent/issues?q=is%3Aissue+is%3Aclosed+sort%3Aupdated-desc
1612
1613<!-- DOWNLOADS -->
1614[gd]: https://badgen.net/npm/dm/got?label
1615[kd]: https://badgen.net/npm/dm/ky?label
1616[rd]: https://badgen.net/npm/dm/request?label
1617[nd]: https://badgen.net/npm/dm/node-fetch?label
1618[ad]: https://badgen.net/npm/dm/axios?label
1619[sd]: https://badgen.net/npm/dm/superagent?label
1620
1621[g3]: https://www.npmjs.com/package/got
1622[k3]: https://www.npmjs.com/package/ky
1623[r3]: https://www.npmjs.com/package/request
1624[n3]: https://www.npmjs.com/package/node-fetch
1625[a3]: https://www.npmjs.com/package/axios
1626[s3]: https://www.npmjs.com/package/superagent
1627
1628<!-- COVERAGE -->
1629[gc]: https://badgen.net/coveralls/c/github/sindresorhus/got?label
1630[kc]: https://badgen.net/codecov/c/github/sindresorhus/ky?label
1631[rc]: https://badgen.net/coveralls/c/github/request/request?label
1632[nc]: https://badgen.net/coveralls/c/github/bitinn/node-fetch?label
1633[ac]: https://badgen.net/coveralls/c/github/mzabriskie/axios?label
1634[sc]: https://badgen.net/codecov/c/github/visionmedia/superagent?label
1635
1636[g4]: https://coveralls.io/github/sindresorhus/got
1637[k4]: https://codecov.io/gh/sindresorhus/ky
1638[r4]: https://coveralls.io/github/request/request
1639[n4]: https://coveralls.io/github/bitinn/node-fetch
1640[a4]: https://coveralls.io/github/mzabriskie/axios
1641[s4]: https://codecov.io/gh/visionmedia/superagent
1642
1643<!-- BUILD -->
1644[gb]: https://badgen.net/travis/sindresorhus/got?label
1645[kb]: https://badgen.net/travis/sindresorhus/ky?label
1646[rb]: https://badgen.net/travis/request/request?label
1647[nb]: https://badgen.net/travis/bitinn/node-fetch?label
1648[ab]: https://badgen.net/travis/axios/axios?label
1649[sb]: https://badgen.net/travis/visionmedia/superagent?label
1650
1651[g5]: https://travis-ci.org/sindresorhus/got
1652[k5]: https://travis-ci.org/sindresorhus/ky
1653[r5]: https://travis-ci.org/request/request
1654[n5]: https://travis-ci.org/bitinn/node-fetch
1655[a5]: https://travis-ci.org/axios/axios
1656[s5]: https://travis-ci.org/visionmedia/superagent
1657
1658<!-- BUGS -->
1659[gbg]: https://badgen.net/github/label-issues/sindresorhus/got/bug/open?label
1660[kbg]: https://badgen.net/github/label-issues/sindresorhus/ky/bug/open?label
1661[rbg]: https://badgen.net/github/label-issues/request/request/Needs%20investigation/open?label
1662[nbg]: https://badgen.net/github/label-issues/bitinn/node-fetch/bug/open?label
1663[abg]: https://badgen.net/github/label-issues/axios/axios/type:bug/open?label
1664[sbg]: https://badgen.net/github/label-issues/visionmedia/superagent/Bug/open?label
1665
1666[g6]: https://github.com/sindresorhus/got/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3Abug
1667[k6]: https://github.com/sindresorhus/ky/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3Abug
1668[r6]: https://github.com/request/request/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A"Needs+investigation"
1669[n6]: https://github.com/bitinn/node-fetch/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3Abug
1670[a6]: https://github.com/axios/axios/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3Atype:bug
1671[s6]: https://github.com/visionmedia/superagent/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3ABug
1672
1673<!-- DEPENDENTS -->
1674[gdp]: https://badgen.net/npm/dependents/got?label
1675[kdp]: https://badgen.net/npm/dependents/ky?label
1676[rdp]: https://badgen.net/npm/dependents/request?label
1677[ndp]: https://badgen.net/npm/dependents/node-fetch?label
1678[adp]: https://badgen.net/npm/dependents/axios?label
1679[sdp]: https://badgen.net/npm/dependents/superagent?label
1680
1681[g7]: https://www.npmjs.com/package/got?activeTab=dependents
1682[k7]: https://www.npmjs.com/package/ky?activeTab=dependents
1683[r7]: https://www.npmjs.com/package/request?activeTab=dependents
1684[n7]: https://www.npmjs.com/package/node-fetch?activeTab=dependents
1685[a7]: https://www.npmjs.com/package/axios?activeTab=dependents
1686[s7]: https://www.npmjs.com/package/visionmedia?activeTab=dependents
1687
1688<!-- INSTALL SIZE -->
1689[gis]: https://badgen.net/packagephobia/install/got?label
1690[kis]: https://badgen.net/packagephobia/install/ky?label
1691[ris]: https://badgen.net/packagephobia/install/request?label
1692[nis]: https://badgen.net/packagephobia/install/node-fetch?label
1693[ais]: https://badgen.net/packagephobia/install/axios?label
1694[sis]: https://badgen.net/packagephobia/install/superagent?label
1695
1696[g8]: https://packagephobia.now.sh/result?p=got
1697[k8]: https://packagephobia.now.sh/result?p=ky
1698[r8]: https://packagephobia.now.sh/result?p=request
1699[n8]: https://packagephobia.now.sh/result?p=node-fetch
1700[a8]: https://packagephobia.now.sh/result?p=axios
1701[s8]: https://packagephobia.now.sh/result?p=superagent
1702
1703[Click here][InstallSizeOfTheDependencies] to see the install size of the Got dependencies.
1704
1705[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
1706
1707## Related
1708
1709- [gh-got](https://github.com/sindresorhus/gh-got) - Got convenience wrapper to interact with the GitHub API
1710- [gl-got](https://github.com/singapore/gl-got) - Got convenience wrapper to interact with the GitLab API
1711- [travis-got](https://github.com/samverschueren/travis-got) - Got convenience wrapper to interact with the Travis API
1712- [graphql-got](https://github.com/kevva/graphql-got) - Got convenience wrapper to interact with GraphQL
1713- [GotQL](https://github.com/khaosdoctor/gotql) - Got convenience wrapper to interact with GraphQL using JSON-parsed queries instead of strings
1714- [got-fetch](https://github.com/alexghr/got-fetch) - Got with a `fetch` interface
1715
1716## Maintainers
1717
1718[![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)
1719---|---
1720[Sindre Sorhus](https://sindresorhus.com) | [Szymon Marczak](https://github.com/szmarczak)
1721
1722###### Former
1723
1724- [Vsevolod Strukchinsky](https://github.com/floatdrop)
1725- [Alexander Tesfamichael](https://github.com/alextes)
1726- [Brandon Smith](https://github.com/brandon93s)
1727- [Luke Childs](https://github.com/lukechilds)
1728
1729---
1730
1731<div align="center">
1732 <b>
1733 <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>
1734 </b>
1735 <br>
1736 <sub>
1737 Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
1738 </sub>
1739</div>