🌐 Human-friendly and powerful HTTP request library for Node.js

Overview


Got


Sindre's open source work is supported by the community.
Special thanks to:








Human-friendly and powerful HTTP request library for Node.js

Coverage Status Downloads Install size

Moving from Request? (Note that Request is unmaintained)

See how Got compares to other HTTP libraries

For browser usage, we recommend Ky by the same people.

Support questions should be asked here.

Highlights

Install

$ npm install got

Usage

Promise
const got = require('got');

(async () => {
	try {
		const response = await got('https://sindresorhus.com');
		console.log(response.body);
		//=> ' ...'
	} catch (error) {
		console.log(error.response.body);
		//=> 'Internal server error ...'
	}
})();
JSON
const got = require('got');

(async () => {
	const {body} = await got.post('https://httpbin.org/anything', {
		json: {
			hello: 'world'
		},
		responseType: 'json'
	});

	console.log(body.data);
	//=> {hello: 'world'}
})();

See JSON mode for more details.

Streams
const stream = require('stream');
const {promisify} = require('util');
const fs = require('fs');
const got = require('got');

const pipeline = promisify(stream.pipeline);

(async () => {
	await pipeline(
		got.stream('https://sindresorhus.com'),
		fs.createWriteStream('index.html')
	);

	// For POST, PUT, PATCH, and DELETE methods, `got.stream` returns a `stream.Writable`.
	await pipeline(
		fs.createReadStream('index.html'),
		got.stream.post('https://sindresorhus.com')
	);
})();

Tip: from.pipe(to) doesn't forward errors. Instead, use stream.pipeline(from, ..., to, callback).

Note: While got.post('https://example.com') resolves, got.stream.post('https://example.com') will hang indefinitely until a body is provided. If there's no body on purpose, remember to .end() the stream or set the body option to an empty string.

API

It's a GET request by default, but can be changed by using different methods or via options.method.

By default, Got will retry on failure. To disable this option, set options.retry to 0.

got(url?, options?)

Returns a Promise giving a Response object or a Got Stream if options.isStream is set to true.

url

Type: string | object

The URL to request, as a string, a https.request options object, or a WHATWG URL.

Properties from options will override properties in the parsed url.

If no protocol is specified, it will throw a TypeError.

Note: The query string is not parsed as search params. Example:

got('https://example.com/?query=a b'); //=> https://example.com/?query=a%20b
got('https://example.com/', {searchParams: {query: 'a b'}}); //=> https://example.com/?query=a+b

// The query string is overridden by `searchParams`
got('https://example.com/?query=a b', {searchParams: {query: 'a b'}}); //=> https://example.com/?query=a+b
options

Type: object

Any of the https.request options.

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.

method

Type: string
Default: GET

The HTTP method used to make the request.

prefixUrl

Type: string | URL

When 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.

Note: prefixUrl will be ignored if the url argument is a URL instance.

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.

Tip: Useful when used with got.extend() to create niche-specific Got instances.

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.

const got = require('got');

(async () => {
	await got('unicorn', {prefixUrl: 'https://cats.com'});
	//=> 'https://cats.com/unicorn'

	const instance = got.extend({
		prefixUrl: 'https://google.com'
	});

	await instance('unicorn', {
		hooks: {
			beforeRequest: [
				options => {
					options.prefixUrl = 'https://cats.com';
				}
			]
		}
	});
	//=> 'https://cats.com/unicorn'
})();
headers

Type: object
Default: {}

Request headers.

Existing headers will be overwritten. Headers set to undefined will be omitted.

isStream

Type: boolean
Default: false

Returns a Stream instead of a Promise. This is equivalent to calling got.stream(url, options?).

body

Type: string | Buffer | stream.Readable or form-data instance

Note #1: The body option cannot be used with the json or form option.

Note #2: If you provide this option, got.stream() will be read-only.

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.

Note #4: This option is not enumerable and will not be merged with the instance defaults.

The content-length header will be automatically set if body is a string / Buffer / form-data instance, and content-length and transfer-encoding are not manually set in options.headers.

Since Got 12, the content-length is not automatically set when body is a fs.createReadStream.

json

Type: object | Array | number | string | boolean | null (JSON-serializable values)

Note #1: If you provide this option, got.stream() will be read-only.
Note #2: This option is not enumerable and will not be merged with the instance defaults.

JSON body. If the Content-Type header is not set, it will be set to application/json.

context

Type: object

User data. context is shallow merged and enumerable. If it contains non-enumerable properties they will NOT be merged.

It's very useful for storing auth tokens:

const got = require('got');

const instance = got.extend({
	hooks: {
		beforeRequest: [
			options => {
				if (!options.context || !options.context.token) {
					throw new Error('Token required');
				}

				options.headers.token = options.context.token;
			}
		]
	}
});

(async () => {
	const context = {
		token: 'secret'
	};

	const response = await instance('https://httpbin.org/headers', {context});

	// Let's see the headers
	console.log(response.body);
})();
responseType

Type: string
Default: 'text'

Note: When using streams, this option is ignored.

The parsing method. Can be 'text', 'json' or 'buffer'.

The promise also has .text(), .json() and .buffer() methods which return another Got promise for the parsed body.
It's like setting the options to {responseType: 'json', resolveBodyOnly: true} but without affecting the main Got promise.

Example:

(async () => {
	const responsePromise = got(url);
	const bufferPromise = responsePromise.buffer();
	const jsonPromise = responsePromise.json();

	const [response, buffer, json] = await Promise.all([responsePromise, bufferPromise, jsonPromise]);
	// `response` is an instance of Got Response
	// `buffer` is an instance of Buffer
	// `json` is an object
})();
// This
const body = await got(url).json();

// is semantically the same as this
const body = await got(url, {responseType: 'json', resolveBodyOnly: true});

Note: buffer will return the raw body buffer. Modifying it will also alter the result of promise.text() and promise.json(). Before overwriting the buffer, please copy it first via Buffer.from(buffer). See https://github.com/nodejs/node/issues/27080

parseJson

Type: (text: string) => unknown
Default: (text: string) => JSON.parse(text)

A function used to parse JSON responses.

Example

Using bourne to prevent prototype pollution:

const got = require('got');
const Bourne = require('@hapi/bourne');

(async () => {
	const parsed = await got('https://example.com', {
		parseJson: text => Bourne.parse(text)
	}).json();

	console.log(parsed);
})();
stringifyJson

Type: (object: unknown) => string
Default: (object: unknown) => JSON.stringify(object)

A function used to stringify the body of JSON requests.

Examples

Ignore properties starting with _:

const got = require('got');

(async () => {
	await got.post('https://example.com', {
		stringifyJson: object => JSON.stringify(object, (key, value) => {
			if (key.startsWith('_')) {
				return;
			}

			return value;
		}),
		json: {
			some: 'payload',
			_ignoreMe: 1234
		}
	});
})();

All numbers as strings:

const got = require('got');

(async () => {
	await got.post('https://example.com', {
		stringifyJson: object => JSON.stringify(object, (key, value) => {
			if (typeof value === 'number') {
				return value.toString();
			}

			return value;
		}),
		json: {
			some: 'payload',
			number: 1
		}
	});
})();
resolveBodyOnly

Type: boolean
Default: false

When set to true the promise will return the Response body instead of the Response object.

cookieJar

Type: object | tough.CookieJar instance

Note: If you provide this option, options.headers.cookie will be overridden.

Cookie support. You don't have to care about parsing or how to store them. Example.

cookieJar.setCookie

Type: Function

The function takes two arguments: rawCookie (string) and url (string).

cookieJar.getCookieString

Type: Function

The function takes one argument: url (string).

ignoreInvalidCookies

Type: boolean
Default: false

Ignore invalid cookies instead of throwing an error. Only useful when the cookieJar option has been set. Not recommended.

encoding

Type: string
Default: 'utf8'

Encoding to be used on setEncoding of the response data.

To get a Buffer, you need to set responseType to buffer instead. Don't set this option to null.

Note: This doesn't affect streams! Instead, you need to do got.stream(...).setEncoding(encoding).

form

Type: object

Note #1: If you provide this option, got.stream() will be read-only.
Note #2: This option is not enumerable and will not be merged with the instance defaults.

The form body is converted to a query string using (new URLSearchParams(object)).toString().

If the Content-Type header is not present, it will be set to application/x-www-form-urlencoded.

searchParams

Type: string | object | URLSearchParams

Query string that will be added to the request URL. This will override the query string in url.

If you need to pass in an array, you can do it using a URLSearchParams instance:

const got = require('got');

const searchParams = new URLSearchParams([['key', 'a'], ['key', 'b']]);

got('https://example.com', {searchParams});

console.log(searchParams.toString());
//=> 'key=a&key=b'

There are some exceptions in regards to URLSearchParams behavior:

Note #1: null values are not stringified, an empty string is used instead.

Note #2: undefined values are not stringified, the entry is skipped instead.

timeout

Type: number | object

Milliseconds to wait for the server to end the response before aborting the request with got.TimeoutError error (a.k.a. request property). By default, there's no timeout.

This also accepts an object with the following fields to constrain the duration of each phase of the request lifecycle:

  • lookup starts when a socket is assigned and ends when the hostname has been resolved. Does not apply when using a Unix domain socket.
  • 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.
  • secureConnect starts when connect completes and ends when the handshaking process completes (HTTPS only).
  • socket starts when the socket is connected. See request.setTimeout.
  • response starts when the request has been written to the socket and ends when the response headers are received.
  • send starts when the socket is connected and ends with the request has been written to the socket.
  • request starts when the request is initiated and ends when the response's end event fires.
  • read starts when the response event is emitted and ends when the response's end event fires.

Note: The read timeout is blocked by https://github.com/nodejs/node/issues/35923

retry

Type: number | object
Default:

  • limit: 2
  • calculateDelay: ({attemptCount, retryOptions, error, computedValue}) => computedValue | Promise
  • methods: GET PUT HEAD DELETE OPTIONS TRACE
  • statusCodes: 408 413 429 500 502 503 504 521 522 524
  • maxRetryAfter: undefined
  • errorCodes: ETIMEDOUT ECONNRESET EADDRINUSE ECONNREFUSED EPIPE ENOTFOUND ENETUNREACH EAI_AGAIN

An object representing limit, calculateDelay, methods, statusCodes, maxRetryAfter and errorCodes fields for maximum retry count, retry handler, allowed methods, allowed status codes, maximum Retry-After time and allowed error codes.

If maxRetryAfter is set to undefined, it will use options.timeout.
If Retry-After header is greater than maxRetryAfter, it will cancel the request.

Delays between retries counts with function 1000 * Math.pow(2, retry - 1) + Math.random() * 100, where retry is attempt number (starts from 1).

The 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 (or a Promise resolving with it) (0 return value cancels retry).

Note: The calculateDelay function is responsible for the entire retry mechanism, including the limit property. To support the limit property, you need to check whether computedValue is different than 0.

By default, it retries only on the specified methods, status codes, and on these network errors:

  • ETIMEDOUT: One of the timeout limits were reached.
  • ECONNRESET: Connection was forcibly closed by a peer.
  • EADDRINUSE: Could not bind to any free port.
  • ECONNREFUSED: Connection was refused by the server.
  • EPIPE: The remote side of the stream being written has been closed.
  • ENOTFOUND: Couldn't resolve the hostname to an IP address.
  • ENETUNREACH: No internet connection.
  • EAI_AGAIN: DNS lookup timed out.

You can retry Got streams too. The implementation looks like this:

const got = require('got');
const fs = require('fs');

let writeStream;

const fn = (retryCount = 0) => {
	const stream = got.stream('https://example.com');
	stream.retryCount = retryCount;

	if (writeStream) {
		writeStream.destroy();
	}

	writeStream = fs.createWriteStream('example.com');

	stream.pipe(writeStream);

	// If you don't attach the listener, it will NOT make a retry.
	// It automatically checks the listener count so it knows whether to retry or not :)
	stream.once('retry', fn);
};

fn();
followRedirect

Type: boolean
Default: true

Defines if redirect responses should be followed automatically.

Note 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.

methodRewriting

Type: boolean
Default: true

Specifies if the redirects should be rewritten as GET.

If false, 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).

allowGetBody

Type: boolean
Default: false

Note: The RFC 7321 doesn't specify any particular behavior for the GET method having a payload, therefore it's considered an anti-pattern.

Set this to true to allow sending body for the GET method. However, the HTTP/2 specification 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.

maxRedirects

Type: number
Default: 10

If exceeded, the request will be aborted and a MaxRedirectsError will be thrown.

decompress

Type: boolean
Default: true

Decompress 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.

Brotli (br) support requires Node.js 11.7.0 or later.

If 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.

cache

Type: object | false
Default: false

Cache adapter instance for storing cached response data.

cacheOptions

Type: object | undefined
Default: {}

Cache options used for the specified request.

dnsCache

Type: CacheableLookup | false
Default: false

An instance of CacheableLookup used for making DNS lookups. Useful when making lots of requests to different public hostnames.

Note: This should stay disabled when making requests to internal hostnames such as localhost, database.local etc.
CacheableLookup uses dns.resolver4(..) and dns.resolver6(...) under the hood and fall backs to dns.lookup(...) when the first two fail, which may lead to additional delay.

dnsLookupIpVersion

Type: 'auto' | 'ipv4' | 'ipv6'
Default: 'auto'

Indicates which DNS record family to use.
Values:

  • auto: IPv4 (if present) or IPv6
  • ipv4: Only IPv4
  • ipv6: Only IPv6

Note: If you are using the undocumented option family, dnsLookupIpVersion will override it.

// `api6.ipify.org` will be resolved as IPv4 and the request will be over IPv4 (the website will respond with your public IPv4)
await got('https://api6.ipify.org', {
	dnsLookupIpVersion: 'ipv4'
});

// `api6.ipify.org` will be resolved as IPv6 and the request will be over IPv6 (the website will respond with your public IPv6)
await got('https://api6.ipify.org', {
	dnsLookupIpVersion: 'ipv6'
});
lookup

Type: Function
Default: dns.lookup

Custom DNS resolution logic.

The function signature is the same as dns.lookup.

request

Type: Function
Default: http.request | https.request (Depending on the protocol)

Custom request function. The main purpose of this is to support HTTP2 using a wrapper.

http2

Type: boolean
Default: false

If set to true, Got will additionally accept HTTP2 requests.

It will choose either HTTP/1.1 or HTTP/2 depending on the ALPN protocol.

Note: This option requires Node.js 15.10.0 or newer as HTTP/2 support on older Node.js versions is very buggy.

Note: Overriding options.request will disable HTTP2 support.

const got = require('got');

(async () => {
	const {headers} = await got('https://nghttp2.org/httpbin/anything', {http2: true});
	console.log(headers.via);
	//=> '2 nghttpx'
})();
throwHttpErrors

Type: boolean
Default: true

Determines if a got.HTTPError is thrown for unsuccessful responses.

If this is disabled, requests that encounter an error status code will be resolved with the response instead of throwing. This may be useful if you are checking for resource availability and are expecting error responses.

agent

Type: object

An object representing http, https and http2 keys for http.Agent, https.Agent and http2wrapper.Agent instance. 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.

If a key is not present, it will default to a global agent.

const got = require('got');
const HttpAgent = require('agentkeepalive');
const {HttpsAgent} = HttpAgent;

got('https://sindresorhus.com', {
	agent: {
		http: new HttpAgent(),
		https: new HttpsAgent()
	}
});
hooks

Type: object

Hooks allow modifications during the request lifecycle. Hook functions may be async and are run serially.

hooks.init

Type: Function[]
Default: []

Called with plain request options, right before their normalization. This is especially useful in conjunction with got.extend() when the input needs custom handling.

See the Request migration guide for an example.

Note #1: This hook must be synchronous!
Note #2: Errors in this hook will be converted into an instances of RequestError.
Note #3: The options object may not have a url property. To modify it, use a beforeRequest hook instead.

hooks.beforeRequest

Type: Function[]
Default: []

Called with normalized request options. Got will make no further changes to the request before it is sent. This is especially useful in conjunction with got.extend() when you want to create an API client that, for example, uses HMAC-signing.

Note: Changing options.json or options.form has no effect on the request, you should change options.body instead. If needed, update the options.headers accordingly. Example:

const got = require('got');

got.post({
	json: {payload: 'old'},
	hooks: {
		beforeRequest: [
			options => {
				options.body = JSON.stringify({payload: 'new'});
				options.headers['content-length'] = options.body.length.toString();
			}
		]
	}
});

Tip: You can override the request function by returning a ClientRequest-like instance or a IncomingMessage-like instance. This is very useful when creating a custom cache mechanism.

hooks.beforeRedirect

Type: Function[]
Default: []

Called with normalized request options and the redirect response. Got will make no further changes to the request. This is especially useful when you want to avoid dead sites. Example:

const got = require('got');

got('https://example.com', {
	hooks: {
		beforeRedirect: [
			(options, response) => {
				if (options.hostname === 'deadSite') {
					options.hostname = 'fallbackSite';
				}
			}
		]
	}
});
hooks.beforeRetry

Type: Function[]
Default: []

Note: When using streams, this hook is ignored.

Called with normalized request 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:

const got = require('got');

got.post('https://example.com', {
	hooks: {
		beforeRetry: [
			(options, error, retryCount) => {
				if (error.response.statusCode === 413) { // Payload too large
					options.body = getNewBody();
				}
			}
		]
	}
});

Note: When retrying in a afterResponse hook, all remaining beforeRetry hooks will be called without the error and retryCount arguments.

hooks.afterResponse

Type: Function[]
Default: []

Note: When using streams, this hook is ignored.

Called with response object and a retry function. Calling the retry function will trigger beforeRetry hooks.

Each function should return the response. This is especially useful when you want to refresh an access token. Example:

const got = require('got');

const instance = got.extend({
	hooks: {
		afterResponse: [
			(response, retryWithMergedOptions) => {
				if (response.statusCode === 401) { // Unauthorized
					const updatedOptions = {
						headers: {
							token: getNewToken() // Refresh the access token
						}
					};

					// Save for further requests
					instance.defaults.options = got.mergeOptions(instance.defaults.options, updatedOptions);

					// Make a new retry
					return retryWithMergedOptions(updatedOptions);
				}

				// No changes otherwise
				return response;
			}
		],
		beforeRetry: [
			(options, error, retryCount) => {
				// This will be called on `retryWithMergedOptions(...)`
			}
		]
	},
	mutableDefaults: true
});
hooks.beforeError

Type: Function[]
Default: []

Called 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.

Note: Errors thrown while normalizing input options are thrown directly and not part of this hook.

const got = require('got');

got('https://api.github.com/some-endpoint', {
	hooks: {
		beforeError: [
			error => {
				const {response} = error;
				if (response && response.body) {
					error.name = 'GitHubError';
					error.message = `${response.body.message} (${response.statusCode})`;
				}

				return error;
			}
		]
	}
});
pagination

Type: object

Note: We're looking for feedback, any ideas on how to improve the API are welcome.

pagination.transform

Type: Function
Default: response => JSON.parse(response.body)

A function that transform Response into an array of items. This is where you should do the parsing.

pagination.paginate

Type: Function
Default: Link header logic

The function takes an object with the following properties:

  • response - The current response object.
  • currentItems - Items from the current response.
  • allItems - An empty array, unless pagination.stackAllItems is set to true, in which case, it's an array of the emitted items.

It should return an object representing Got options pointing to the next page. The options are merged automatically with the previous request, therefore the options returned pagination.paginate(...) must reflect changes only. If there are no more pages, false should be returned.

For example, if you want to stop when the response contains less items than expected, you can use something like this:

const got = require('got');

(async () => {
	const limit = 10;

	const items = got.paginate('https://example.com/items', {
		searchParams: {
			limit,
			offset: 0
		},
		pagination: {
			paginate: ({response, currentItems, allItems}) => {
				const previousSearchParams = response.request.options.searchParams;
				const previousOffset = previousSearchParams.get('offset');

				if (currentItems.length < limit) {
					return false;
				}

				return {
					searchParams: {
						...previousSearchParams,
						offset: Number(previousOffset) + limit,
					}
				};
			}
		}
	});

	console.log('Items from all pages:', items);
})();
pagination.filter

Type: Function
Default: ({item, currentItems, allItems}) => true

Checks whether the item should be emitted or not.

pagination.shouldContinue

Type: Function
Default: ({item, currentItems, allItems}) => true

Checks whether the pagination should continue.

For example, if you need to stop before emitting an entry with some flag, you should use ({item}) => !item.flag. If you want to stop after emitting the entry, you should use ({item, allItems}) => allItems.some(item => item.flag) instead.

pagination.countLimit

Type: number
Default: Infinity

The maximum amount of items that should be emitted.

pagination.backoff

Type: number
Default: 0

Milliseconds to wait before the next request is triggered.

pagination.requestLimit

Type: number
Default: 10000

The maximum amount of request that should be triggered. Retries on failure are not counted towards this limit.

For example, it can be helpful during development to avoid an infinite number of requests.

pagination.stackAllItems

Type: boolean
Default: false

Defines how the property allItems in pagination.paginate, pagination.filter and pagination.shouldContinue is managed.

By default, the property allItems is always an empty array. This setting can be helpful to save on memory usage when working with a large dataset.

When set to true, the property allItems is an array of the emitted items.

localAddress

Type: string

The IP address used to send the request from.

Advanced HTTPS API

Note: If the request is not HTTPS, these options will be ignored.

https.certificateAuthority

Type: string | Buffer | Array

Override the default Certificate Authorities (from Mozilla)

// Single Certificate Authority
got('https://example.com', {
	https: {
		certificateAuthority: fs.readFileSync('./my_ca.pem')
	}
});
https.key

Type: string | Buffer | Array | object[]

Private keys in PEM format.
PEM allows the option of private keys being encrypted. Encrypted keys will be decrypted with options.https.passphrase.
Multiple keys with different passphrases can be provided as an array of {pem: , passphrase: }

https.certificate

Type: string | Buffer | (string | Buffer)[]

Certificate chains in PEM format.
One cert chain should be provided per private key (options.https.key).
When providing multiple cert chains, they do not have to be in the same order as their private keys in options.https.key.
If the intermediate certificates are not provided, the peer will not be able to validate the certificate, and the handshake will fail.

https.passphrase

Type: string

The passphrase to decrypt the options.https.key (if different keys have different passphrases refer to options.https.key documentation).

https.pfx

Type: string | Buffer | Array

PFX or PKCS12 encoded private key and certificate chain. Using options.https.pfx is an alternative to providing options.https.key and options.https.certificate individually. A PFX is usually encrypted, and if it is, options.https.passphrase will be used to decrypt it.

Multiple PFX's can be be provided as an array of unencrypted buffers or an array of objects like:

{
	buffer: string | Buffer,
	passphrase?: string
}

This object form can only occur in an array. If the provided buffers are encrypted, object.passphrase can be used to decrypt them. If object.passphrase is not provided, options.https.passphrase will be used for decryption.

Examples for https.key, https.certificate, https.passphrase, and https.pfx
// Single key with certificate
got('https://example.com', {
	https: {
		key: fs.readFileSync('./client_key.pem'),
		certificate: fs.readFileSync('./client_cert.pem')
	}
});

// Multiple keys with certificates (out of order)
got('https://example.com', {
	https: {
		key: [
			fs.readFileSync('./client_key1.pem'),
			fs.readFileSync('./client_key2.pem')
		],
		certificate: [
			fs.readFileSync('./client_cert2.pem'),
			fs.readFileSync('./client_cert1.pem')
		]
	}
});

// Single key with passphrase
got('https://example.com', {
	https: {
		key: fs.readFileSync('./client_key.pem'),
		certificate: fs.readFileSync('./client_cert.pem'),
		passphrase: 'client_key_passphrase'
	}
});

// Multiple keys with different passphrases
got('https://example.com', {
	https: {
		key: [
			{pem: fs.readFileSync('./client_key1.pem'), passphrase: 'passphrase1'},
			{pem: fs.readFileSync('./client_key2.pem'), passphrase: 'passphrase2'},
		],
		certificate: [
			fs.readFileSync('./client_cert1.pem'),
			fs.readFileSync('./client_cert2.pem')
		]
	}
});

// Single encrypted PFX with passphrase
got('https://example.com', {
	https: {
		pfx: fs.readFileSync('./fake.pfx'),
		passphrase: 'passphrase'
	}
});

// Multiple encrypted PFX's with different passphrases
got('https://example.com', {
	https: {
		pfx: [
			{
				buffer: fs.readFileSync('./key1.pfx'),
				passphrase: 'passphrase1'
			},
			{
				buffer: fs.readFileSync('./key2.pfx'),
				passphrase: 'passphrase2'
			}
		]
	}
});

// Multiple encrypted PFX's with single passphrase
got('https://example.com', {
	https: {
		passphrase: 'passphrase',
		pfx: [
			{
				buffer: fs.readFileSync('./key1.pfx')
			},
			{
				buffer: fs.readFileSync('./key2.pfx')
			}
		]
	}
});
https.rejectUnauthorized

Type: boolean
Default: true

If set to false, all invalid SSL certificates will be ignored and no error will be thrown.
If set to true, it will throw an error whenever an invalid SSL certificate is detected.

We strongly recommend to have this set to true for security reasons.

const got = require('got');

(async () => {
	// Correct:
	await got('https://example.com', {
		https: {
			rejectUnauthorized: true
		}
	});

	// You can disable it when developing an HTTPS app:
	await got('https://localhost', {
		https: {
			rejectUnauthorized: false
		}
	});

	// Never do this:
	await got('https://example.com', {
		https: {
			rejectUnauthorized: false
		}
	});
https.checkServerIdentity

Type: Function
Signature: (hostname: string, certificate: DetailedPeerCertificate) => Error | undefined
Default: tls.checkServerIdentity (from the tls module)

This function enable a custom check of the certificate.
Note: In order to have the function called the certificate must not be expired, self-signed or with an untrusted-root.
The function parameters are:

  • hostname: The server hostname (used when connecting)
  • certificate: The server certificate

The function must return undefined if the check succeeded or an Error if it failed.

await got('https://example.com', {
	https: {
		checkServerIdentity: (hostname, certificate) => {
			if (hostname === 'example.com') {
				return; // Certificate OK
			}

			return new Error('Invalid Hostname'); // Certificate NOT OK
		}
	}
});

Response

The response object will typically be a Node.js HTTP response stream, however, if returned from the cache it will be a response-like object which behaves in the same way.

request

Type: object

Note: This is not a http.ClientRequest.

  • options - The Got options that were set on this request.
body

Type: string | object | Buffer (Depending on options.responseType)

The result of the request.

rawBody

Type: Buffer

The raw result of the request.

url

Type: string

The request URL or the final URL after redirects.

ip

Type: string

The remote IP address.

Note: Not available when the response is cached. This is hopefully a temporary limitation, see lukechilds/cacheable-request#86.

requestUrl

Type: string

The original request URL.

timings

Type: object

The object contains the following properties:

  • start - Time when the request started.
  • socket - Time when a socket was assigned to the request.
  • lookup - Time when the DNS lookup finished.
  • connect - Time when the socket successfully connected.
  • secureConnect - Time when the socket securely connected.
  • upload - Time when the request finished uploading.
  • response - Time when the request fired response event.
  • end - Time when the response fired end event.
  • error - Time when the request fired error event.
  • abort - Time when the request fired abort event.
  • phases
    • wait - timings.socket - timings.start
    • dns - timings.lookup - timings.socket
    • tcp - timings.connect - timings.lookup
    • tls - timings.secureConnect - timings.connect
    • request - timings.upload - (timings.secureConnect || timings.connect)
    • firstByte - timings.response - timings.upload
    • download - timings.end - timings.response
    • total - (timings.end || timings.error || timings.abort) - timings.start

If something has not been measured yet, it will be undefined.

Note: The time is a number representing the milliseconds elapsed since the UNIX epoch.

isFromCache

Type: boolean

Whether the response was retrieved from the cache.

redirectUrls

Type: string[]

The redirect URLs.

retryCount

Type: number

The number of times the request was retried.

Streams

Note: Progress events, redirect events and request/response events can also be used with promises.

Note: To access response.isFromCache you need to use got.stream(url, options).isFromCache. The value will be undefined until the response event.

got.stream(url, options?)

Sets options.isStream to true.

Returns a duplex stream with additional events:

.on('request', request)

request event to get the request object of the request.

Tip: You can use request event to abort request:

got.stream('https://github.com')
	.on('request', request => setTimeout(() => request.destroy(), 50));
.on('response', response)

The response event to get the response object of the final request.

.on('redirect', response, nextOptions)

The redirect event to get the response object of a redirect. The second argument is options for the next request to the redirect location.

.on('uploadProgress', progress)
.uploadProgress
.on('downloadProgress', progress)
.downloadProgress

Progress events for uploading (sending a request) and downloading (receiving a response). The progress argument is an object like:

{
	percent: 0.1,
	transferred: 1024,
	total: 10240
}

If the content-length header is missing, total will be undefined.

(async () => {
	const response = await got('https://sindresorhus.com')
		.on('downloadProgress', progress => {
			// Report download progress
		})
		.on('uploadProgress', progress => {
			// Report upload progress
		});

	console.log(response);
})();
.once('retry', retryCount, error)

To enable retrying on a Got stream, it is required to have a retry handler attached.
When this event is emitted, you should reset the stream you were writing to and prepare the body again.

See the retry option for an example implementation.

.ip

Type: string

The remote IP address.

.aborted

Type: boolean

Indicates whether the request has been aborted or not.

.timings

The same as response.timings.

.isFromCache

The same as response.isFromCache.

.socket

The same as response.socket.

.on('error', error)

The emitted error is an instance of RequestError.

Pagination

got.paginate(url, options?)

got.paginate.each(url, options?)

Returns an async iterator:

(async () => {
	const countLimit = 10;

	const pagination = got.paginate('https://api.github.com/repos/sindresorhus/got/commits', {
		pagination: {countLimit}
	});

	console.log(`Printing latest ${countLimit} Got commits (newest to oldest):`);

	for await (const commitData of pagination) {
		console.log(commitData.commit.message);
	}
})();

See options.pagination for more pagination options.

got.paginate.all(url, options?)

Returns a Promise for an array of all results:

(async () => {
	const countLimit = 10;

	const results = await got.paginate.all('https://api.github.com/repos/sindresorhus/got/commits', {
		pagination: {countLimit}
	});

	console.log(`Printing latest ${countLimit} Got commits (newest to oldest):`);
	console.log(results);
})();

See options.pagination for more pagination options.

got.get(url, options?)

got.post(url, options?)

got.put(url, options?)

got.patch(url, options?)

got.head(url, options?)

got.delete(url, options?)

Sets options.method to the method name and makes a request.

Instances

got.extend(...options)

Configure a new got instance with default options. The options are merged with the parent instance's defaults.options using got.mergeOptions. You can access the resolved options with the .defaults property on the instance.

const client = got.extend({
	prefixUrl: 'https://example.com',
	headers: {
		'x-unicorn': 'rainbow'
	}
});

client.get('demo');

/* HTTP Request =>
 * GET /demo HTTP/1.1
 * Host: example.com
 * x-unicorn: rainbow
 */
(async () => {
	const client = got.extend({
		prefixUrl: 'httpbin.org',
		headers: {
			'x-foo': 'bar'
		}
	});
	const {headers} = await client.get('headers').json();
	//=> headers['x-foo'] === 'bar'

	const jsonClient = client.extend({
		responseType: 'json',
		resolveBodyOnly: true,
		headers: {
			'x-baz': 'qux'
		}
	});
	const {headers: headers2} = await jsonClient.get('headers');
	//=> headers2['x-foo'] === 'bar'
	//=> headers2['x-baz'] === 'qux'
})();

Additionally, got.extend() accepts two properties from the defaults object: mutableDefaults and handlers. Example:

// You can now modify `mutableGot.defaults.options`.
const mutableGot = got.extend({mutableDefaults: true});

const mergedHandlers = got.extend({
	handlers: [
		(options, next) => {
			delete options.headers.referer;

			return next(options);
		}
	]
});

Note: Handlers can be asynchronous. The recommended approach is:

const handler = (options, next) => {
	if (options.isStream) {
		// It's a Stream
		return next(options);
	}

	// It's a Promise
	return (async () => {
		try {
			const response = await next(options);
			response.yourOwnProperty = true;
			return response;
		} catch (error) {
			// Every error will be replaced by this one.
			// Before you receive any error here,
			// it will be passed to the `beforeError` hooks first.
			// Note: this one won't be passed to `beforeError` hook. It's final.
			throw new Error('Your very own error.');
		}
	})();
};

const instance = got.extend({handlers: [handler]});

got.extend(...options, ...instances, ...)

Merges many instances into a single one:

  • options are merged using got.mergeOptions() (including hooks),
  • handlers are stored in an array (you can access them through instance.defaults.handlers).
const a = {headers: {cat: 'meow'}};
const b = got.extend({
	options: {
		headers: {
			cow: 'moo'
		}
	}
});

// The same as `got.extend(a).extend(b)`.
// Note `a` is options and `b` is an instance.
got.extend(a, b);
//=> {headers: {cat: 'meow', cow: 'moo'}}

got.mergeOptions(parent, ...sources)

Extends parent options. Avoid using object spread as it doesn't work recursively:

const a = {headers: {cat: 'meow', wolf: ['bark', 'wrrr']}};
const b = {headers: {cow: 'moo', wolf: ['auuu']}};

{...a, ...b}            // => {headers: {cow: 'moo', wolf: ['auuu']}}
got.mergeOptions(a, b)  // => {headers: {cat: 'meow', cow: 'moo', wolf: ['auuu']}}

Note: Only Got options are merged! Custom user options should be defined via options.context.

Options are deeply merged to a new object. The value of each key is determined as follows:

  • If the new property is not defined, the old value is used.
  • If the new property is explicitly set to undefined:
    • If the parent property is a plain object, the parent value is deeply cloned.
    • Otherwise, undefined is used.
  • If the parent value is an instance of URLSearchParams:
    • If the new value is a string, an object or an instance of URLSearchParams, a new URLSearchParams instance is created. The values are merged using urlSearchParams.append(key, value). The keys defined in the new value override the keys defined in the parent value. Please note that null values point to an empty string and undefined values will exclude the entry.
    • Otherwise, the only available value is undefined.
  • If the new property is a plain object:
    • If the parent property is a plain object too, both values are merged recursively into a new object.
    • Otherwise, only the new value is deeply cloned.
  • If the new property is an Array, it overwrites the old one with a deep clone of the new property.
  • Properties that are not enumerable, such as context, body, json, and form, will not be merged.
  • Otherwise, the new value is assigned to the key.
const a = {json: {cat: 'meow'}};
const b = {json: {cow: 'moo'}};

got.mergeOptions(a, b);
//=> {json: {cow: 'moo'}}

got.defaults

Type: object

The Got defaults used in that instance.

options
handlers

Type: Function[]
Default: []

An 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 or asStream, depending on the options.isStream property.

Each handler takes two arguments:

options
next()

Returns a Promise or a Stream depending on options.isStream.

const settings = {
	handlers: [
		(options, next) => {
			if (options.isStream) {
				// It's a Stream, so we can perform stream-specific actions on it
				return next(options)
					.on('request', request => {
						setTimeout(() => {
							request.abort();
						}, 50);
					});
			}

			// It's a Promise
			return next(options);
		}
	],
	options: got.mergeOptions(got.defaults.options, {
		responseType: 'json'
	})
};

const jsonGot = got.extend(settings);
mutableDefaults

Type: boolean
Default: false

A read-only boolean describing whether the defaults are mutable or not. If set to true, you can update headers over time, for example, update an access token when it expires.

Types

Got exports some handy TypeScript types and interfaces. See the type definition for all the exported types.

Got

TypeScript 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.

import {GotRequestFunction} from 'got';

interface Dependencies {
	readonly post: GotRequestFunction
}

Hooks

When writing hooks, you can refer to their types to keep your interfaces consistent.

import {BeforeRequestHook} from 'got';

const addAccessToken = (accessToken: string): BeforeRequestHook => options => {
	options.path = `${options.path}?access_token=${accessToken}`;
}

Errors

Each error contains an options property which are the options Got used to create a request - just to make debugging easier.
Additionally, the errors may have request (Got Stream) and response (Got Response) properties depending on which phase of the request failed.

got.RequestError

When a request fails. Contains a code property with error class code, like ECONNREFUSED. All the errors below inherit this one.

got.CacheError

When a cache method fails, for example, if the database goes down or there's a filesystem error.

got.ReadError

When reading from response stream fails.

got.ParseError

When server response code is 2xx, and parsing body fails. Includes a response property.

got.UploadError

When the request body is a stream and an error occurs while reading from that stream.

got.HTTPError

When the server response code is not 2xx nor 3xx if options.followRedirect is true, but always except for 304. Includes a response property.

got.MaxRedirectsError

When the server redirects you more than ten times. Includes a response property.

got.UnsupportedProtocolError

When given an unsupported protocol.

got.TimeoutError

When the request is aborted due to a timeout. Includes an event and timings property.

got.CancelError

When the request is aborted with .cancel().

Aborting the request

The promise returned by Got has a .cancel() method which when called, aborts the request.

(async () => {
	const request = got(url, options);

	// …

	// In another part of the code
	if (something) {
		request.cancel();
	}

	// …

	try {
		await request;
	} catch (error) {
		if (request.isCanceled) { // Or `error instanceof got.CancelError`
			// Handle cancelation
		}

		// Handle other errors
	}
})();

When using hooks, simply throw an error to abort the request.

const got = require('got');

(async () => {
	const request = got(url, {
		hooks: {
			beforeRequest: [
				() => {
					throw new Error('Oops. Request canceled.');
				}
			]
		}
	});

	try {
		await request;
	} catch (error) {
		// …
	}
})();

To abort the Got Stream request, just call stream.destroy().

const got = require('got');

const stream = got.stream(url);
stream.destroy();

Cache

Got implements RFC 7234 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. For DNS cache, Got uses cacheable-lookup.

You can use the JavaScript Map type as an in-memory cache:

const got = require('got');

const map = new Map();

(async () => {
		let response = await got('https://sindresorhus.com', {cache: map});
		console.log(response.isFromCache);
		//=> false

		response = await got('https://sindresorhus.com', {cache: map});
		console.log(response.isFromCache);
		//=> true
})();

Got uses Keyv internally to support a wide range of storage adapters. For something more scalable you could use an official Keyv storage adapter:

$ npm install @keyv/redis
const got = require('got');
const KeyvRedis = require('@keyv/redis');

const redis = new KeyvRedis('redis://user:pass@localhost:6379');

got('https://sindresorhus.com', {cache: redis});

Got supports anything that follows the Map API, so it's easy to write your own storage adapter or use a third-party solution.

For example, the following are all valid storage adapters:

const storageAdapter = new Map();
// Or
const storageAdapter = require('./my-storage-adapter');
// Or
const QuickLRU = require('quick-lru');
const storageAdapter = new QuickLRU({maxSize: 1000});

got('https://sindresorhus.com', {cache: storageAdapter});

View the Keyv docs for more information on how to use storage adapters.

Proxies

You can use the tunnel package with the agent option to work with proxies:

const got = require('got');
const tunnel = require('tunnel');

got('https://sindresorhus.com', {
	agent: {
		https: tunnel.httpsOverHttp({
			proxy: {
				host: 'localhost'
			}
		})
	}
});

Otherwise, you can use the hpagent package, which keeps the internal sockets alive to be reused.

const got = require('got');
const {HttpsProxyAgent} = require('hpagent');

got('https://sindresorhus.com', {
	agent: {
		https: new HttpsProxyAgent({
			keepAlive: true,
			keepAliveMsecs: 1000,
			maxSockets: 256,
			maxFreeSockets: 256,
			scheduling: 'lifo',
			proxy: 'https://localhost:8080'
		})
	}
});

Alternatively, use global-agent to configure a global proxy for all HTTP/HTTPS traffic in your program.

Read the http2-wrapper docs to learn about proxying for HTTP/2.

Cookies

You can use the tough-cookie package:

const {promisify} = require('util');
const got = require('got');
const {CookieJar} = require('tough-cookie');

(async () => {
	const cookieJar = new CookieJar();
	const setCookie = promisify(cookieJar.setCookie.bind(cookieJar));

	await setCookie('foo=bar', 'https://example.com');
	await got('https://example.com', {cookieJar});
})();

Form data

You can use the form-data package to create POST request with form data:

const fs = require('fs');
const got = require('got');
const FormData = require('form-data');

const form = new FormData();

form.append('my_file', fs.createReadStream('/foo/bar.jpg'));

got.post('https://example.com', {
	body: form
});

OAuth

You can use the oauth-1.0a package to create a signed OAuth request:

const got = require('got');
const crypto  = require('crypto');
const OAuth = require('oauth-1.0a');

const oauth = OAuth({
	consumer: {
		key: process.env.CONSUMER_KEY,
		secret: process.env.CONSUMER_SECRET
	},
	signature_method: 'HMAC-SHA1',
	hash_function: (baseString, key) => crypto.createHmac('sha1', key).update(baseString).digest('base64')
});

const token = {
	key: process.env.ACCESS_TOKEN,
	secret: process.env.ACCESS_TOKEN_SECRET
};

const url = 'https://api.twitter.com/1.1/statuses/home_timeline.json';

got(url, {
	headers: oauth.toHeader(oauth.authorize({url, method: 'GET'}, token)),
	responseType: 'json'
});

Unix Domain Sockets

Requests can also be sent via unix domain sockets. Use the following URL scheme: PROTOCOL://unix:SOCKET:PATH.

  • PROTOCOL - http or https (optional)
  • SOCKET - Absolute path to a unix domain socket, for example: /var/run/docker.sock
  • PATH - Request path, for example: /v2/keys
const got = require('got');

got('http://unix:/var/run/docker.sock:/containers/json');

// Or without protocol (HTTP by default)
got('unix:/var/run/docker.sock:/containers/json');

AWS

Requests to AWS services need to have their headers signed. This can be accomplished by using the got4aws package. This is an example for querying an "API Gateway" with a signed request.

const got4aws = require('got4aws');;

const awsClient = got4aws();

const response = await awsClient('https://.execute-api..amazonaws.com//endpoint/path', {
	// Request-specific options
});

Testing

You can test your requests by using the nock package to mock an endpoint:

const got = require('got');
const nock = require('nock');

nock('https://sindresorhus.com')
	.get('/')
	.reply(200, 'Hello world!');

(async () => {
	const response = await got('https://sindresorhus.com');
	console.log(response.body);
	//=> 'Hello world!'
})();

Bear in mind, that by default nock mocks only one request. Got will retry on failed requests by default, causing a No match for request ... error. The solution is to either disable retrying (set options.retry to 0) or call .persist() on the mocked request.

const got = require('got');
const nock = require('nock');

const scope = nock('https://sindresorhus.com')
	.get('/')
	.reply(500, 'Internal server error')
	.persist();

(async () => {
	try {
		await got('https://sindresorhus.com')
	} catch (error) {
		console.log(error.response.body);
		//=> 'Internal server error'

		console.log(error.response.retryCount);
		//=> 2
	}

	scope.persist(false);
})();

For real integration testing we recommend using ava with 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:

test('retry function gets iteration count', withServer, async (t, server, got) => {
	let knocks = 0;
	server.get('/', (request, response) => {
		if (knocks++ === 1) {
			response.end('who`s there?');
		}
	});

	await got({
		retry: {
			calculateDelay: ({attemptCount}) => {
				t.true(is.number(attemptCount));
				return attemptCount < 2 ? 1 : 0;
			}
		}
	});
});

Tips

JSON mode

To pass an object as the body, you need to use the json option. It will be stringified using JSON.stringify. Example:

const got = require('got');

(async () => {
	const {body} = await got.post('https://httpbin.org/anything', {
		json: {
			hello: 'world'
		},
		responseType: 'json'
	});

	console.log(body.data);
	//=> '{"hello":"world"}'
})();

To receive a JSON body you can either set responseType option to json or use promise.json(). Example:

const got = require('got');

(async () => {
	const body = await got.post('https://httpbin.org/anything', {
		json: {
			hello: 'world'
		}
	}).json();

	console.log(body);
	//=> {…}
})();

User Agent

It'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.

const got = require('got');
const pkg = require('./package.json');

got('https://sindresorhus.com', {
	headers: {
		'user-agent': `my-package/${pkg.version} (https://github.com/username/my-package)`
	}
});

got('https://sindresorhus.com', {
	headers: {
		'user-agent': undefined
	}
});

304 Responses

Bear 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.

Custom endpoints

Use got.extend() to make it nicer to work with REST APIs. Especially if you use the prefixUrl option.

const got = require('got');
const pkg = require('./package.json');

const custom = got.extend({
	prefixUrl: 'example.com',
	responseType: 'json',
	headers: {
		'user-agent': `my-package/${pkg.version} (https://github.com/username/my-package)`
	}
});

// Use `custom` exactly how you use `got`
(async () => {
	const list = await custom('v1/users/list');
})();

FAQ

Why yet another HTTP client?

Got was created because the popular request package is bloated: Install size
Furthermore, Got is fully written in TypeScript and actively maintained.

Electron support has been removed

The Electron net module is not consistent with the Node.js http module. See #899 for more info.

Comparison

got request node-fetch ky axios superagent
HTTP/2 support βœ”οΈ ΒΉ ❌ ❌ ❌ ❌ βœ”οΈ **
Browser support ❌ ❌ βœ”οΈ * βœ”οΈ βœ”οΈ βœ”οΈ
Promise API βœ”οΈ βœ”οΈ βœ”οΈ βœ”οΈ βœ”οΈ βœ”οΈ
Stream API βœ”οΈ βœ”οΈ Node.js only ❌ ❌ βœ”οΈ
Pagination API βœ”οΈ ❌ ❌ ❌ ❌ ❌
Request cancelation βœ”οΈ ❌ βœ”οΈ βœ”οΈ βœ”οΈ βœ”οΈ
RFC compliant caching βœ”οΈ ❌ ❌ ❌ ❌ ❌
Cookies (out-of-box) βœ”οΈ βœ”οΈ ❌ ❌ ❌ ❌
Follows redirects βœ”οΈ βœ”οΈ βœ”οΈ βœ”οΈ βœ”οΈ βœ”οΈ
Retries on failure βœ”οΈ ❌ ❌ βœ”οΈ ❌ βœ”οΈ
Progress events βœ”οΈ ❌ ❌ βœ”οΈ *** Browser only βœ”οΈ
Handles gzip/deflate βœ”οΈ βœ”οΈ βœ”οΈ βœ”οΈ βœ”οΈ βœ”οΈ
Advanced timeouts βœ”οΈ ❌ ❌ ❌ ❌ ❌
Timings βœ”οΈ βœ”οΈ ❌ ❌ ❌ ❌
Errors with metadata βœ”οΈ ❌ ❌ βœ”οΈ βœ”οΈ ❌
JSON mode βœ”οΈ βœ”οΈ βœ”οΈ βœ”οΈ βœ”οΈ βœ”οΈ
Custom defaults βœ”οΈ βœ”οΈ ❌ βœ”οΈ βœ”οΈ ❌
Composable βœ”οΈ ❌ ❌ ❌ ❌ βœ”οΈ
Hooks βœ”οΈ ❌ ❌ βœ”οΈ βœ”οΈ ❌
Issues open
Issues closed
Downloads
Coverage
Build
Bugs
Dependents
Install size
GitHub stars
TypeScript support
Last commit

* It's almost API compatible with the browser fetch API.
** Need to switch the protocol manually. Doesn't accept PUSH streams and doesn't reuse HTTP/2 sessions.
*** Currently, only DownloadProgress event is supported, UploadProgress event is not supported.
ΒΉ Requires Node.js 15.10.0 or above. ❇️ Almost-stable feature, but the API may change. Don't hesitate to try it out!
❔ Feature in early stage of development. Very experimental.

Click here to see the install size of the Got dependencies.

Related

  • gh-got - Got convenience wrapper to interact with the GitHub API
  • gl-got - Got convenience wrapper to interact with the GitLab API
  • travis-got - Got convenience wrapper to interact with the Travis API
  • graphql-got - Got convenience wrapper to interact with GraphQL
  • GotQL - Got convenience wrapper to interact with GraphQL using JSON-parsed queries instead of strings
  • got-fetch - Got with a fetch interface

Maintainers

Sindre Sorhus Szymon Marczak Giovanni Minotti
Sindre Sorhus Szymon Marczak Giovanni Minotti
Former

These amazing companies are using Got


Segment is a happy user of Got! Got powers the main backend API that our app talks to. It's used by our in-house RPC client that we use to communicate with all microservices.

β€” Vadim Demedes

Antora, a static site generator for creating documentation sites, uses Got to download the UI bundle. In Antora, the UI bundle (aka theme) is maintained as a separate project. That project exports the UI as a zip file we call the UI bundle. The main site generator downloads that UI from a URL using Got and streams it to vinyl-zip to extract the files. Those files go on to be used to create the HTML pages and supporting assets.

β€” Dan Allen

GetVoIP is happily using Got in production. One of the unique capabilities of Got is the ability to handle Unix sockets which enables us to build a full control interfaces for our docker stack.

β€” Daniel Kalen

We're using Got inside of Exoframe to handle all the communication between CLI and server. Exoframe is a self-hosted tool that allows simple one-command deployments using Docker.

β€” Tim Ermilov

Karaoke Mugen uses Got to fetch content updates from its online server.

β€” Axel Terizaki

Renovate uses Got, gh-got and gl-got to send millions of queries per day to GitHub, GitLab, npmjs, PyPi, Packagist, Docker Hub, Terraform, CircleCI, and more.

β€” Rhys Arkins

Resistbot uses Got to communicate from the API frontend where all correspondence ingresses to the officials lookup database in back.

β€” Chris Erickson

Natural Cycles is using Got to communicate with all kinds of 3rd-party REST APIs (over 9000!).

β€” Kirill Groshkov

Microlink is a cloud browser as an API service that uses Got widely as the main HTTP client, serving ~22M requests a month, every time a network call needs to be performed.

β€” Kiko Beats

We’re using Got at Radity. Thanks for such an amazing work!

β€” Mirzayev Farid

For enterprise

Available as part of the Tidelift Subscription.

The maintainers of got and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. Learn more.

Comments
  • Got v10 beta feedback

    Got v10 beta feedback

    This issue is for discussing the upcoming Got v10 version which is now in ~alpha~ beta.

    Beta 1: https://github.com/sindresorhus/got/releases/tag/v10.0.0-beta.1

    Let us know if you encounter any issues with upgrading or if anything is unclear in the release notes.

    opened by sindresorhus 101
  • HTTP2 support

    HTTP2 support

    Issuehunt badges

    Hi!

    Can you consider adding HTTP2 support to GOT? Currently the most used client library is this: https://github.com/molnarg/node-http2

    Thank you!


    IssueHunt Summary

    szmarczak szmarczak has been rewarded.

    Backers (Total: $200.00)

    Submitted pull Requests


    Tips

    enhancement work in progress :gift: Rewarded on Issuehunt 
    opened by gunta 54
  • "RequestError: socket hang up" in `.json()` within `afterResponse` hook and agent keepAlive

    Describe the bug

    • Node.js version: 12.16.1
    • OS & version: lastest MacOS

    Updating from working got@10 to [email protected]

    Consider this snippet:

        const opportunitiesIterator = client.paginate<Opportunity>('Opportunities', {
          json: { filter: [{ someField: 'someValue' }] },
        });
        for await (const record of opportunitiesIterator) {
          // Some processing
        }
    

    the client variable is a [email protected] instance with the following notable options:

    • agent with Agent({ keepAlive: true }) for both http and https
    • prefixUrl with public https base url of our Sugar CRM rest api
    • allowGetBody as true for most CRM queries implies an http GET with a body full of json
    • hooks.afterResponse with an async function to acquire/renew OAuth token
    • mutableDefaults as true
    • pagination.paginate and pagination.transform

    Actual behavior

    Upon first evaluation of for await (const record of opportunitiesIterator) there is this error:

    βœ– [ERROR] RequestError: socket hang up
        at ClientRequest.<anonymous> (/Users/guillaumec/rc-dev/rcsf/node_modules/got/dist/source/core/index.js:759:25)
        at Object.onceWrapper (events.js:418:26)
        at ClientRequest.emit (events.js:323:22)
        at ClientRequest.origin.emit (/Users/guillaumec/rc-dev/rcsf/node_modules/@szmarczak/http-timer/dist/source/index.js:39:20)
        at TLSSocket.socketCloseListener (_http_client.js:400:11)
        at TLSSocket.emit (events.js:323:22)
        at net.js:668:12
        at connResetException (internal/errors.js:604:14)
        at TLSSocket.socketCloseListener (_http_client.js:400:25)
        at TLSSocket.emit (events.js:323:22)
        at net.js:668:12
        at TCP.done (_tls_wrap.js:556:7) {
      name: 'RequestError',
      code: 'ECONNRESET',
      timings: {
        start: 1587549556887,
        socket: 1587549556887,
        lookup: undefined,
        connect: undefined,
        secureConnect: undefined,
        upload: undefined,
        response: undefined,
        end: undefined,
        error: 1587549556888,
        abort: 1587549556889,
        phases: {
          wait: 0,
          dns: undefined,
          tcp: undefined,
          tls: undefined,
          request: undefined,
          firstByte: undefined,
          download: undefined,
          total: 2
        }
      }
    }
    

    Expected behavior

    Well, it shouldn't crash, should it?

    Code to reproduce

    // working on it...
    

    Checklist

    • [x] I have read the documentation.
    • [x] I have tried my code with the latest version of Node.js and Got.
    bug external 
    opened by PopGoesTheWza 47
  • Add `cache` option

    Add `cache` option

    Resolves #281

    To keep track of what's implemented:

    • [x] Allow user to pass in a cache store (copy Map() API)
    • [x] Cache responses that are cacheable
    • [x] Return cached responses immediately if still fresh
    • [x] If expired send If-Modified-Since/If-None-Match header
    • [x] Handle potential 304 response
    • [x] Tests
    • [x] Refactor into external module
    • [x] Write some cache adapters
    • [x] Documentation

    Ok I hacked this together last night, I'm aware there are a few things that need tidying up / potentially unhandled errors etc. Just submitting this PR for some feedback.

    I'm caching the url/headers/body of all responses that satisfy:

    (opts.cache && statusCode === 200 && req.method === 'GET' && (expired(response.headers) === false || 'etag' in response.headers))
    

    This is working, I can view them in the cache. The issue is to serve them up I need to create a Node.js response (or similar) object to be passed through Got's asPromise()/asStream() fns and to make sure all the usual response API methods are available on the returned object. I was hoping http-response-object was gonna do the job here but it looks like it only implements a basic subset of the Node.js response object.

    When I emit the response-like object I get:

    UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): TypeError: inputStream.once is not a function
    

    I think this is coming from getStream() because http-response-object doesn't implement some stream stuff from the Node.js response object.

    Any thoughts? I'm kind of out of my depth here in regards to streams and the native response object. Is there is simpler way to do this? Or maybe a straight forward way to create a fake request object?

    // @sindresorhus @reconbot @AlexTes

    opened by lukechilds 45
  • JSON option when posting data

    JSON option when posting data

    Would it be possible to use the json: true option when posting data to set Content-Type to application/json and stringify the body with JSON.stringify?

    enhancement βœ­ help wanted ✭ 
    opened by paglias 43
  • Got 12 planning

    Got 12 planning

    There are a few issues: https://github.com/sindresorhus/got/milestone/9

    Anything else we want to change that is risky or breaking? It doesn't have to be a big breaking release though.

    • [x] Rename lookup option to dnsLookup
    • [ ] Throw an error here: https://github.com/sindresorhus/got/blob/2b40da2247016f2f4f2b2049a40aa51265161259/source/create.ts#L138-L149

    // @szmarczak @Giotino

    opened by sindresorhus 40
  • Got v10 brainstorming

    Got v10 brainstorming

    I would prefer not doing a breaking release for a long time, but that doesn't mean we can't brainstorm.

    Feel free to suggest breaking changes here. Suggestions should include use-cases and why it's worth doing a breaking change.

    • [x] When the query string is an object, but not URLSearchParams, we should enforce that all the keys are string|number. To avoid issues like https://github.com/sindresorhus/got/issues/638.
    • [x] Rename the query option to searchParams.
    • [x] Use undefined instead of null whenever possible.
    future 
    opened by sindresorhus 38
  • Help debugging ECONNRESET problems

    Help debugging ECONNRESET problems

    What would you like to discuss?

    My tool uses [email protected] and regularly get these types of error from npmjs:

    {
        "name": "RequestError",
        "code": "ECONNRESET",
        "host": "registry.npmjs.org",
        "hostname": "registry.npmjs.org",
        "method": "GET",
        "path": "/@typescript-eslint%2Feslint-plugin",
        "protocol": "https:",
        "url": "https://registry.npmjs.org/@typescript-eslint%2Feslint-plugin",
        "gotOptions": {
          "path": "/@typescript-eslint%2Feslint-plugin",
          "protocol": "https:",
          "slashes": true,
          "auth": null,
          "host": "registry.npmjs.org",
          "port": null,
          "hostname": "registry.npmjs.org",
          "hash": null,
          "search": null,
          "query": null,
          "pathname": "/@typescript-eslint%2Feslint-plugin",
          "href": "https://registry.npmjs.org/@typescript-eslint%2Feslint-plugin",
          "headers": {
            "user-agent": "Renovate Bot (GitHub App 2740)",
            "authorization": "** redacted **",
            "cache-control": "no-cache",
            "accept": "application/json",
            "accept-encoding": "gzip, deflate"
          },
          "hooks": {
            "beforeError": [],
            "init": [],
            "beforeRequest": [],
            "beforeRedirect": [],
            "beforeRetry": [],
            "afterResponse": []
          },
          "retry": {
            "methods": {},
            "statusCodes": {},
            "errorCodes": {}
          },
          "decompress": true,
          "throwHttpErrors": true,
          "followRedirect": true,
          "stream": false,
          "form": false,
          "json": true,
          "cache": false,
          "useElectronNet": false,
          "method": "GET"
        },
        "message": "read ECONNRESET",
        "stack": "RequestError: read ECONNRESET\n    at ClientRequest.request.once.error (/home/ubuntu/renovateapp/node_modules/got/source/request-as-event-emitter.js:178:14)\n    at Object.onceWrapper (events.js:286:20)\n    at ClientRequest.emit (events.js:203:15)\n    at ClientRequest.EventEmitter.emit (domain.js:448:20)\n    at ClientRequest.origin.emit.args (/home/ubuntu/renovateapp/node_modules/@szmarczak/http-timer/source/index.js:37:11)\n    at TLSSocket.socketErrorListener (_http_client.js:392:9)\n    at TLSSocket.emit (events.js:198:13)\n    at TLSSocket.EventEmitter.emit (domain.js:448:20)\n    at emitErrorNT (internal/streams/destroy.js:91:8)\n    at emitErrorAndCloseNT (internal/streams/destroy.js:59:3)"
      },
    

    I'm wondering, does the retry part above indicate that there's actually no retrying? Or could it indicate an incomplete stringifying of the object, etc?

    Additionally, is there any additional debugging of the err object I can do once such errors are thrown?

    Checklist

    • [x] I have read the documentation.
    opened by rarkins 35
  • Uncaught TypeError: Cannot read property 'once' of undefined     at EventEmitter.ee.once.req

    Uncaught TypeError: Cannot read property 'once' of undefined at EventEmitter.ee.once.req

    I'm attempting to use got from the browser with browserify. Looking through the issues I see others have had success, but I'm currently getting an error when using it. My request completes with the correct respsonse but an error come with it.

    Uncaught TypeError: Cannot read property 'once' of undefined
        at EventEmitter.ee.once.req (bundle.js:10705)
        at EventEmitter.g (bundle.js:7590)
        at EventEmitter.emit (bundle.js:7521)
        at setImmediate (bundle.js:10740)
        at onNextTick (bundle.js:9657)
        at Item.run (bundle.js:8030)
        at drainQueue (bundle.js:8000)
    

    The code is a fairly simple example.

    const got = require('got')
    global.setImmediate = require('timers').setImmediate
    
    const options = {
            method: 'GET'
    }
    
    got('https://api.github.com', options)
            .then(x => console.log(x.body))
            .catch(console.log)
    

    I'm running this command to make my bundle.js file

    browserify index.js > bundle.js
    

    Have I done something incorrectly?

    opened by austinfrey 35
  • Don't force query string normalization

    Don't force query string normalization

    What problem are you trying to solve?

    In an url like http://example.org/random?param=SOMETHING~SOMETHING the special character ~ is percent-encoded before the request, resulting in http://example.org/random?param=SOMETHING%7ESOMETHING which is not supported (decoded) by some HTTP servers.

    As described by RFC 3986 in section 2.3 " URI comparison implementations do not always perform normalization prior to comparison. For consistency, percent-encoded octets in the ranges of ALPHA (%41-%5A and %61-%7A), DIGIT (%30-%39), hyphen (%2D), period (%2E), underscore (%5F), or tilde (%7E) should not be created by URI producers and, when found in a URI, should be decoded to their corresponding unreserved characters by URI normalizers. "

    Also in RFC 3986, section 6.2.2.2 " The percent-encoding mechanism is a frequent source of variance among otherwise identical URIs. In addition to the case normalization issue noted above, some URI producers percent-encode octets that do not require percent-encoding, resulting in URIs that are equivalent to their non-encoded counterparts. These URIs should be normalized by decoding any percent-encoded octet that corresponds to an unreserved character, as described in Section 2.3. "

    The percent-encoding of ~ by got happen because NodeJS follows the "WHATWG URL API" (https://nodejs.org/api/url.html#url_the_whatwg_url_api) which misses ~ from the unreserved characters (https://url.spec.whatwg.org/#interface-urlsearchparams, the Note below the example, and https://url.spec.whatwg.org/#urlencoded-serializing) and, by the way, includes *.

    Describe the feature

    My proposal is to add a flag to the options to prevent the normalization by skipping the append and delete of "_GOT_INTERNAL_TRIGGER_NORMALIZATION"

    Checklist

    • [x] I have read the documentation and made sure this feature doesn't already exist.
    enhancement 
    opened by Giotino 34
  • Intermittent uncaught errors

    Intermittent uncaught errors

    With got version 9.2.2, I'm seeing timed-out crash occasionally with an unhandled error event. I'm using the promise API, not the stream-based one, so I expect this event to always be turned into a promise rejection.

    TimeoutError: Timeout awaiting 'response' for 2000ms 
      at Immediate.timeoutHandler (/node_modules/got/source/timed-out.js:39:25) 
    
    bug 
    opened by timdp 34
  • node v18's FormData

    node v18's FormData "-\n-" will become "-\r\n-"

    Describe the bug

    • Node.js version: v18.12.1
    • OS & version: Darwin qm.local 22.2.0 Darwin Kernel Version 22.2.0: Fri Nov 11 02:08:47 PST 2022; root:xnu-8792.61.2~4/RELEASE_X86_64 x86_64

    Actual behavior

    request:

    // node global.FormData,not npm
    form = new FormData();
        form.set('imN_notRN','a\na');
    
    // print :    imN_notRN value "a\na"  
        console.log('imN_notRN value',JSON.stringify(form.get('imN_notRN')))
    
      // php "echo json_encode($_POST);"  will print :    { imN_notRN: 'a\r\na' } 
       console.log (await got({
            url: 'http://127.0.0.1:8000/?',
            method: 'POST',
            body: form,
            responseType: 'json'
        }).json());
    

    Expected behavior

    php "echo json_encode($_POST);" will print : { imN_notRN: 'a\na' }

    Code to reproduce

    ...
    

    Checklist

    • [ ] I have read the documentation.
    • [ ] I have tried my code with the latest version of Node.js and Got.
    opened by qidizi 0
  • Context will remain same through out a request ?

    Context will remain same through out a request ?

    What would you like to discuss?

    • There is no discription talking much about when the context is getting updated / created.
    • Im having a use case where i need to identify each request with an id but not able to pass those id as header to server
    • I need to know whether the context is recreated for each request and will persisit.
    • When i tested the same it works as expected but need a conformation before the actual usage.

    image

    Checklist

    • [x] I have read the documentation.
    opened by amal-chandran 0
  • [fix] URI malformed error with valid encoded latin1 URL

    [fix] URI malformed error with valid encoded latin1 URL

    There are still sites in the wild that only support Latin1 encoded URLs, but GOT throws a URI malformed error even though the page can be retrieved. This PR removes the assertion made with decodeURI to solve the problem.

    My question would be, why is decodeURI used here for assertion?

    Samples:

    • http://www.wrgag.ch/Inserat_Servicemonteur_L%FCftung_Klima.pdf

    Checklist

    • [x] I have read the documentation.
    • [x] I have included a pull request description of my changes.
    • [ ] I have included some tests.
    • [ ] If it's a new feature, I have included documentation updates in both the README and the types.
    opened by xhaggi 0
  • Getting Errors on HTTPS / LTS, unsigned certificates and disabled authorization

    Getting Errors on HTTPS / LTS, unsigned certificates and disabled authorization

    Describe the bug

    • Node.js version: v18.0.0
    • OS & version: macOS 13.0.1

    There an issue on LTS and HTTP error while I have authorization disabled.

    Actual behavior

    While using @mgcrea/node-tydom-client im running into new "TLS" issue for localhost request. The client only use get requests from got, I have NODE_TLS_REJECT_UNAUTHORIZED=0 configured.

    However my request still get denied, with the following error:

    (node:8950) Warning: Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to '0' makes TLS connections and HTTPS requests insecure by disabling certificate verification.
    (Use `node --trace-warnings ...` to show where the warning was created)
    
    /Users/lifely/Desktop/playground/tydom/node_modules/got/dist/source/core/index.js:970
                error = error instanceof timed_out_1.TimeoutError ? new TimeoutError(error, this.timings, this) : new RequestError(error.message, error, this);
                                                                                                                  ^
    RequestError: write EPROTO 00A5B50E02000000:error:0A000152:SSL routines:final_renegotiate:unsafe legacy renegotiation disabled:../deps/openssl/openssl/ssl/statem/extensions.c:908:
    
        at ClientRequest.<anonymous> (/Users/lifely/Desktop/playground/tydom/node_modules/got/dist/source/core/index.js:970:111)
        at Object.onceWrapper (node:events:642:26)
        at ClientRequest.emit (node:events:539:35)
        at ClientRequest.emit (node:domain:475:12)
        at ClientRequest.origin.emit (/Users/lifely/Desktop/playground/tydom/node_modules/@szmarczak/http-timer/dist/source/index.js:43:20)
        at TLSSocket.socketErrorListener (node:_http_client:454:9)
        at TLSSocket.emit (node:events:527:28)
        at TLSSocket.emit (node:domain:475:12)
        at emitErrorNT (node:internal/streams/destroy:151:8)
        at emitErrorCloseNT (node:internal/streams/destroy:116:3)
        at WriteWrap.onWriteComplete [as oncomplete] (node:internal/stream_base_commons:94:16)
    

    I've tried setting up global-agent to debug what's going on, but the request works find going through my local proxy.

    Expected behavior

    The request should works both with or with-out proxy.

    opened by lifely 1
  • RequestError: The `body` option must be a stream.Readable, string or Buffer

    RequestError: The `body` option must be a stream.Readable, string or Buffer

    I am getting this error while trying to hit the POST, and PUT APIs.

    Software specifications: GOT: 11.8.6 OS: Windows 10 Node: 16.18.1 NPM: 8.19.2

    Code Snippet const gotObject = { method: req.method, json: true, body: req.body, headers: reqHeader, }; const apiResponse = await got(microserviceUrl, gotObject);

    Error Stack 2022-12-19T11:38:44.708Z - error: [D:\Projects\NodeJs\gateway\src\services\microservice.ts] callService at Request._destroy (D:\Projects\NodeJs\node-api-gateway\node_modules\got\dist\source\core\index.js:1386:21) at _destroy (node:internal/streams/destroy:102:25) at Request.destroy (node:internal/streams/destroy:64:5) at D:\Projects\NodeJs\node-api-gateway\node_modules\got\dist\source\core\index.js:354:26 at processTicksAndRejections (node:internal/process/task_queues:96:5) at Request._finalizeBody (D:\Projects\NodeJs\node-api-gateway\node_modules\got\dist\source\core\index.js:726:23) at D:\Projects\NodeJs\node-api-gateway\node_modules\got\dist\source\core\index.js:333:28 at new Request (D:\Projects\NodeJs\node-api-gateway\node_modules\got\dist\source\core\index.js:357:11) at makeRequest (D:\Projects\NodeJs\node-api-gateway\node_modules\got\dist\source\as-promise\index.js:35:29)

    Checklist

    • [ ] I have read the ReadMe page but no specification is found on this.
    opened by ketavchotaliya 3
  • Handlers cannot throw custom errors.

    Handlers cannot throw custom errors.

    Describe the bug

    • Node.js version: v16.14.0
    • OS & version: macOS Monterey (12.6.1)

    The documentation page includes an example of a handler that throws a custom error to replace the original error. This example does not work and any error you throw from within a handler will leak (unless you have an unhandledRejection listener to do something with it).

    I tested this with a handler that is pretty much identical to the recommendation in the docs:

        const got = Got.extend( { handlers : [
          ( options, next ) => {
            return ( async () => {
              try {
                return await next( options );
              } catch ( error ) {
                throw new Error( 'Replacement Error' );
              }
            } )();
          },
        ] } );
        await got( `https://httpstat.us/404` ).json();
    

    Actual behavior

    Throwing an error from a handler leaks a promise that will be rejected with the new error, and has no effect on the result of the request. If the actual HTTP request was successful then the got request will be resolved successfully, ignoring the error that was thrown in the handler. If the actual HTTP request was unsuccessful then any error you throw from the handler will again be ignored, and the got request will be resolved with whatever the original failure was.

    Running the script included below produces this:

    Attempting to replace error
    [FAIL] Got wrong error: Response code 404 (Not Found)
    [FAIL] Got unhandled rejection: Replacement Error
    
    Throwing error on successful request
    [FAIL] Did not expect a successful response
    [FAIL] Got unhandled rejection: Async Error
    

    Expected behavior

    Throwing an error from a handler causes the request to be rejected with that error.

    I expected that the script below would produce this:

    Attempting to replace error
    [PASS] Got correct error
    
    Throwing error on successful request
    [PASS] Got correct error
    

    Code to reproduce

    Here is a more complete and runnable test script

    #!/usr/bin/env node
    import Got from 'got';
    
    process.on( 'unhandledRejection', err => {
      console.log( `[FAIL] Got unhandled rejection: ${err.message}` );
    } );
    
    async function replaceError() {
      try {
        const got = Got.extend( { handlers : [
          ( options, next ) => {
            return ( async () => {
              try {
                return await next( options );
              } catch ( error ) {
                throw new Error( 'Replacement Error' );
              }
            } )();
          },
        ] } );
        return await got( `https://httpstat.us/404` ).json();
      } catch ( err ) {
        if ( err.message === 'Replacement Error' ) {
          console.log( '[PASS] Got correct error' );
        } else {
          console.log( '[FAIL] Got wrong error:', err.message );
        }
      }
    }
    
    async function throwOnSuccessfulRequest() {
      try {
        const got = Got.extend( { handlers : [
          ( options, next ) => {
            return ( async () => {
              await next( options );
              throw new Error( 'Async Error' );
            } )();
          },
        ] } );
        await got( `https://httpstat.us/200` ).json();
        console.log( '[FAIL] Did not expect a successful response' );
      } catch ( err ) {
        if ( err.message === 'Async Error' ) {
          console.log( '[PASS] Got correct error' );
        } else {
          console.log( '[FAIL] Got wrong error:', err.message );
        }
      }
    }
    
    // This interval just makes sure that node keeps the script running
    // until all the promises are resolved.
    const interval = setInterval( () => {}, 1000 );
    
    console.log( 'Attempting to replace error' );
    await replaceError();
    
    // This is just to make sure that the unhandled rejection is detected
    // before we move on to the next test
    await new Promise( resolve => setTimeout( resolve, 1000 ) );
    
    console.log( '\nThrowing error on successful request' );
    await throwOnSuccessfulRequest();
    
    clearInterval( interval );
    

    Checklist

    • [x] I have read the documentation.
    • [x] I have tried my code with the latest version of Node.js and Got.
    opened by jasonk 1
Releases(v11.8.6)
  • v11.8.6(Dec 8, 2022)

  • v12.5.3(Nov 16, 2022)

  • v12.5.2(Oct 12, 2022)

  • v12.5.1(Sep 27, 2022)

    • Fix compatibility with TypeScript and ESM 3b3ea67
    • Fix request body not being properly cached (#2150) 3e9d3af

    https://github.com/sindresorhus/got/compare/v12.5.0...v12.5.1

    Source code(tar.gz)
    Source code(zip)
  • v12.5.0(Sep 19, 2022)

    • Disable method rewriting on 307 and 308 status codes (#2145) e049e94
    • Upgrade dependencies 8630815 f0ac0b3 4c3762a

    https://github.com/sindresorhus/got/compare/v12.4.1...v12.5.0

    Source code(tar.gz)
    Source code(zip)
  • v12.4.1(Sep 2, 2022)

    Fixes

    • Fix options.context being not extensible b671480715dbbff908e9a385f5e714570c663cd7
    • Don't emit uploadProgress after promise cancelation 693de217b030816f574d6e4cb505ee2e77b21c29

    https://github.com/sindresorhus/got/compare/v12.4.0...v12.4.1

    Source code(tar.gz)
    Source code(zip)
  • v12.4.0(Sep 2, 2022)

    Improvements

    • Support FormData without known length (#2120) 850773c

    Fixes

    • Don't call beforeError hooks with HTTPError if the throwHttpErrors option is false (#2104) 3927348

    https://github.com/sindresorhus/got/compare/v12.3.1...v12.4.0

    Source code(tar.gz)
    Source code(zip)
  • v12.3.1(Aug 6, 2022)

  • v12.3.0(Jul 28, 2022)

  • v12.2.0(Jul 24, 2022)

  • v12.1.0(May 25, 2022)

  • v11.8.5(May 25, 2022)

  • v12.0.4(Apr 24, 2022)

  • v12.0.3(Mar 26, 2022)

  • v12.0.2(Mar 16, 2022)

  • v12.0.1(Jan 9, 2022)

    • Fix nock compatibility (#1959) bf39d2c
    • Fix missing export of Request TypeScript type (#1940) 0f9f2b8

    https://github.com/sindresorhus/got/compare/v12.0.0...v12.0.1

    Source code(tar.gz)
    Source code(zip)
  • v12.0.0(Dec 10, 2021)

    Introducing Got v12.0.0 :tada:

    Long time no see! The latest Got version (v11.8.2) was released just in February ❄️ We have been working hard on squashing bugs and improving overall experience.

    If you find Got useful, you might want to sponsor the Got maintainers.

    This package is now pure ESM

    Please read this. Also see https://github.com/sindresorhus/got/issues/1789.

    • Please don't open issues about [ERR_REQUIRE_ESM] and Must use import to load ES Module errors. This is a problem with your setup, not Got.
    • Please don't open issues about using Got with Jest. Jest does not fully support ESM.
    • Pretty much any problem with loading this package is a problem with your bundler, test framework, etc, not Got.
    • If you use TypeScript, you will want to stay on Got v11 until TypeScript 4.6 is out. Why.
    • If you use a bundler, make sure it supports ESM and that you have correctly configured it for ESM.
    • The Got issue tracker is not a support channel for your favorite build/bundler tool.

    Required Node.js >=14

    While working with streams, we encountered more Node.js bugs that needed workarounds. In order to keep our code clean, we had to drop Node.js v12 as the code would get more messy. We strongly recommend that you update Node.js to v14 LTS.

    HTTP/2 support

    Every Node.js release, the native http2 module gets more stable. Unfortunately there are still some issues on the Node.js side, so we decided to keep HTTP/2 disabled for now. We may enable it by default in Got v13. It is still possible to turn it on via the http2 option.

    To run HTTP/2 requests, it is required to use Node.js v15.10 or above.

    Bug fixes

    Woah, we possibly couldn't make a release if we didn't fix some bugs!

    • Do not throw on custom stack traces (#1491) 49c16ee54fb19ea7aa77e24ac8c2b602f0aad265
    • Remove automatic content-length on ReadStream (#1510) 472b8ef9d9fc7713b740981a8b1103a7a9111b26
    • Fix promise shortcuts in case of error status code (#1543) ff918fb6dedb6d8b23421497ec890d43f45121b7 1107cc625e4cc469276483316c48896a21f6251a
    • Invert the methodRewriting option 51d88a0efed56760d116c5b911cea71e3265c787
    • Fix url not being reused on retry in rare case (#1487) 462bc630015064fa4ad4358cf28d24f95e1c958b
    • Fix hanging promise on HTTP/2 timeout (#1492) a59fac415ac013a48b1d514837628a5cf81d6878
    • Prevent uncaught ParseErrors on initial successful response (#1527) 77df9c33db5ba3126f54317171e1cfcfceefc3d5
    • Throw an error when retrying with consumed body (#1507) 62305d77d3428b5c714d21b4bbee68cc75b5f787
    • Fix a Node.js 16 bug that hangs Got streams 06a2d3d7d8d4fcc6898b6364d1a18ca1d407092b
    • Fix default pagination handling for empty Link header (#1768) 1e1e50647e93d038a4cc6a9bbbfbf61165d8fd39
    • Fix incorrect response.complete when using cache 9e15d887da3b065940bbc8ca38f9c748a0bbc75e
    • Fix Cannot call end error when request returns a Writable 226cc3995f6e16938163ebde24d8762e7dcd15e2
    • Fix Request options not being reused on retry 3c23eea5a096f6f8ea0edf3e2a27e1caca88acf9
    • Fix types being not compatible with CommonJS 3c23eea5a096f6f8ea0edf3e2a27e1caca88acf9
    • Fix got.paginate does not call init hooks (#1574) 3c23eea5a096f6f8ea0edf3e2a27e1caca88acf9
    • Generate a new object when passing options to the native https module (#1567) 3c23eea5a096f6f8ea0edf3e2a27e1caca88acf9
    • Remove stream reuse check (#1803) 9ecc5ee76f77aafd5100520d9d8789c491c8fb24
    • Fix merging searchParams (#1814) 1018c2029eea1f5b75b5120265996f1c0b3c12ae 732e9bd9406ba1c3dd64b445264e891f33fc0254
    • Fix unhandled exception when lookup returns invalid IP early (#1737) 2453e5e4213fe036a0108de3e4db414dcf2b4c30
    • Fix relative URLs when paginating 439fb82d2a07cece417a18c47e37cfdeaaf38db7
    • Require url to be an instance of URL when paginating (#1818) eda69ff924a621e499d31cbc590993a32ddb48d3
    • Fix username and password encoding in URL (#1169 #1317) d65d0caf627e8d1f5367db34d7d9b55d332c1efb
    • Clone raw options 1c4cefc9b49f891712c3758f853d8c6214a1c904
    • Fix invalid afterResponse return check cbc8902
    • Fix https.alpnProtocols not having an effect e1099fb

    Improvements

    • Make the context option mergeable (#1459) 2b8ed1f5a185f30603d24e2ceb8181782de3bc5a
    • Add generic argument to AfterResponseHook TypeScript type (#1589) 6fc04a9b92f07b07b9fba010f2231a90082a039b
    • Add read timeout (#1518) e9436720fcb32b77d39d5477b420b18083e41c02 (blocked by https://github.com/nodejs/node/issues/35923)
    • Improve the pagination API (#1644) 2675046a83c7f03613f553a8da2912d491be900d
    • Change the stackAllItems option to be false by default (#1645) 1120370e05fd8d9e768677d8474d0c82cf91a6a6
    • Throw when afterResponse hook returns an invalid value 4f21eb3db705c90797ef8ee1503704f78fea3c1b
    • Add retry.backoffLimit option 41c4136632b9391adb3ac53332b312089bc4dc16
    • Add noise retry option e83007704670b5f567ca338c156441f6c569ecb5
    • Enable more HTTPS options 83575d590a119027d319bd9208681973087564a9 fe723a0477dc02785a0b477e3d5f85d0233e5b84 (thanks @Giotino)
    • Define error.code f27e8d331627074e76e4a9ec85a2c8d0a0625e5f
    • Set options.url even if some options are invalid 8d6a6807883323a83ea5f126ca56b55d9ce5f299
    • Improve memory usage when merging options 2db5ec5d366efbbf9e0838eabfa6be774a0518a0
    • Support async generators as body 854430f01350811fe8a0ccf20cd820aabfbd3926 3df52f38edbadb45158c37d499817bc5486989c6
    • Add missing once types for Stream API 3c23eea5a096f6f8ea0edf3e2a27e1caca88acf9
    • New error type: RetryError which always triggers a new retry when thrown 3c23eea5a096f6f8ea0edf3e2a27e1caca88acf9
    • error.options is now enumerable 3c23eea5a096f6f8ea0edf3e2a27e1caca88acf9
    • defaults.handlers don't need a default handler now 3c23eea5a096f6f8ea0edf3e2a27e1caca88acf9
    • Add a parser for the Link header 3c23eea5a096f6f8ea0edf3e2a27e1caca88acf9
    • General code improvements a5dd9aa37e7891b2620798560799c7f8bd380877

    Breaking changes

    Improved option normalization

    • Got exports an Option class that is specifically designed to parse and validate Got options. It is made of setters and getters that provide fast normalization and more consistent behavior.

    When passing an option does not exist, Got will throw an error. In order to retrieve the options before the error, use error.options.

    import got from 'got';
    
    try {
        await got('https://httpbin.org/anything', {
            thisOptionDoesNotExist: true
        });
    } catch (error) {
        console.error(error);
        console.error(error.options.url.href);
        // Unexpected option: thisOptionDoesNotExist
        // https://httpbin.org/anything
    }
    
    • The init hook now accepts a second argument: self, which points to an Options instance.

    In order to define your own options, you have to move them to options.context in an init hook or store them in options.context directly.

    • The init hooks are ran only when passing an options object explicitly.
    - await got('https://example.com'); // this will *not* trigger the init hooks
    + await got('https://example.com', {}); // this *will** trigger init hooks
    
    - got.defaults.options = got.mergeOptions(got.defaults.options, {…});
    + got.defaults.options.merge(…);
    

    This fixes issues like #1450

    • Legacy Url instances are not supported anymore. You need to use WHATWG URL instead.
    - await got(string, {port: 8443});
    + const url = new URL(string);
    + url.port = 8443;
    + await got(url);
    
    • No implicit timeout declaration.
    - await got('https://example.com', {timeout: 5000})
    + await got('https://example.com', {timeout: {request: 5000})
    
    • No implicit retry declaration.
    - await got('https://example.com', {retry: 5})
    + await got('https://example.com', {retry: {limit: 5})
    
    • dnsLookupIpVersion is now a number (4 or 6) or undefined
    - await got('https://example.com', {dnsLookupIpVersion: 'ipv4'})
    + await got('https://example.com', {dnsLookupIpVersion: 4})
    
    • redirectUrls and requestUrl now give URL instances
    - request.requestUrl
    + request.requestUrl.origin
    + request.requestUrl.href
    + request.requestUrl.toString()
    
    - request.redirectUrls[0]
    + request.redirectUrls[0].origin
    + request.redirectUrls[0].href
    + request.redirectUrls[0].toString()
    
    • Renamed request.aborted to request.isAborted
    - request.aborted
    + request.isAborted
    

    Reason: consistency with options.isStream.

    • Renamed the lookup option to dnsLookup
    - await got('https://example.com', {lookup: cacheable.lookup})
    + await got('https://example.com', {dnsLookup: cacheable.lookup})
    
    • The beforeRetry hook now accepts only two arguments: error and retryCount
    await got('https://example.com', {
        hooks: {
            beforeRetry: [
    -            (options, error, retryCount) => {
    -                console.log(options, error, retryCount);
    -            }
    +            (error, retryCount) => {
    +                console.log(error.options, error, retryCount);
    +            }
            ]
        }
    })
    

    The options argument has been removed, however it's still accessible via error.options. All modifications on error.options will be reflected in the next requests (no behavior change, same as with Got 11).

    • The beforeRedirect hook's first argument (options) is now a cloned instance of the Request options.

    This was done to make retrieving the original options possible: plainResponse.request.options.

    await got('http://szmarczak.com', {
        hooks: {
            beforeRedirect: [
                (options, response) => {
    -                console.log(options === response.request.options); //=> true [invalid! our original options were overriden]
    +                console.log(options === response.request.options); //=> false [we can access the original options now]
                }
            ]
        }
    })
    
    • The redirect event now takes two arguments in this order: updatedOptions and plainResponse.
    - stream.on('redirect', (response, options) => …)
    + stream.on('redirect', (options, response) => …)
    

    Reason: consistency with the beforeRedirect hook.

    • The socketPath option has been removed. Use the unix: protocol instead.
    - got('/containers/json', {socketPath: '/var/run/docker.sock'})
    + got('unix:/var/run/docker.sock:/containers/json')
    + got('http://unix:/var/run/docker.sock:/containers/json')
    
    • The retryWithMergedOptions function in an afterResponse hook no longer returns a Promise.

    It now throws RetryError, so this should this should be the last function being executed. This was done to allow beforeRetry hooks getting called.

    • You can no longer set options.agent to false. To do so, you need to define all the options.agent properties: http, https and http2.
    await got('https://example.com', {
    -    agent: false
    +    agent: {
    +        http: false,
    +        https: false,
    +        http2: false
    +    }
    })
    
    • When passing a url option when paginating, it now needs to be an absolute URL - the prefixUrl option is always reset from now on. The same when retrying in an afterResponse hook.
    - return {url: '/location'};
    + return {url: new URL('/location', response.request.options.url)};
    

    There was confusion around the prefixUrl option. It was counterintuitive if used with the Pagination API. For example, it worked fine if the server replied with a relative URL, but if it was an absolute URL then the prefixUrl would end up duplicated. In order to fix this, Got now requires an absolute URL - no prefixUrl will be applied.

    • got.extend(…) will throw when passing some options that don't accept undefined - undefined no longer retains the old value, as setting undefined explicitly may reset the option

    Documentation

    We have redesigned the documentation so it's easier to navigate and find exactly what you are looking for. We hope you like it :heart:

    Source code(tar.gz)
    Source code(zip)
  • v11.8.3(Nov 18, 2021)

    • Bump cacheable-request dependency (#1921) 9463bb6
    • Fix HTTPError missing .code property (#1739) 0e167b8

    https://github.com/sindresorhus/got/compare/v11.8.2...v11.8.3

    Source code(tar.gz)
    Source code(zip)
  • v12.0.0-beta.4(Aug 12, 2021)

    • Fix invalid afterResponse return check cbc8902
    • Clarify retryWithMergedOptions valid hooks (#1832) 15c30ee
    • Add Apify to Showcase (#1828) 3386bf1
    • Add got-scraping to Got plugins in readme (#1823) 7805501
    • Fix https.alpnProtocols not having an effect e1099fb
    Source code(tar.gz)
    Source code(zip)
  • v12.0.0-beta.3(Aug 6, 2021)

    Bug fixes

    • Clone raw options 1c4cefc9b49f891712c3758f853d8c6214a1c904

    Previously Got 12 was freezing the options instead of cloning, but it seems this is too breaking. Reverted option freezing so the behavior matches Got 11.

    Source code(tar.gz)
    Source code(zip)
  • v12.0.0-beta.2(Aug 4, 2021)

    v12.0.0-beta.2 introduces more stability fixes! Yay!

    Bug fixes

    • Remove stream reuse check (#1803) 9ecc5ee76f77aafd5100520d9d8789c491c8fb24
    • Fix merging searchParams (#1814) 1018c2029eea1f5b75b5120265996f1c0b3c12ae 732e9bd9406ba1c3dd64b445264e891f33fc0254
    • Fix unhandled exception when lookup returns invalid IP early (#1737) 2453e5e4213fe036a0108de3e4db414dcf2b4c30
    • Fix relative URLs when paginating 439fb82d2a07cece417a18c47e37cfdeaaf38db7
    • Require url to be an instance of URL when paginating (#1818) eda69ff924a621e499d31cbc590993a32ddb48d3
    • Fix username and password encoding in URL (#1169 #1317) d65d0caf627e8d1f5367db34d7d9b55d332c1efb

    Improvements

    • General code improvements a5dd9aa37e7891b2620798560799c7f8bd380877

    Documentation

    • Add an example of uppercase headers 3dc2ad9bf5d101b4b74c00e4ce9237c8218ce24d
    • Add docs for custom options (#1794) 6a44a8158a0f62ded055625f9aeec028abc880f3
    Source code(tar.gz)
    Source code(zip)
  • v12.0.0-beta.1(Jul 22, 2021)

    We are pleased to announce Got v12.0.0 beta 1! :tada: It's been a year and three months since Got 11 was released, and the latest Got version (v11.8.2) was released just in February ❄️ During that time, we have been working hard on squashing bugs and improving overall experience.

    If you find Got useful, you might want to sponsor the Got maintainers.

    This package is now pure ESM

    Please read this. Also see https://github.com/sindresorhus/got/issues/1789.

    Required Node.js >=14

    While working with streams, we encountered more Node.js bugs that needed workarounds. In order to keep our code clean, we had to drop Node.js v12 as the code would get more messy. We strongly recommend that you update Node.js to v14 LTS.

    HTTP/2 support

    Every Node.js release, the native http2 module gets more stable. Unfortunately there are still some issues on the Node.js side, so we decided to keep HTTP/2 disabled for now. We may enable it by default in Got v13. It is still possible to turn it on via the http2 option.

    To run HTTP/2 requests, it is required to use Node.js v15.10 or above.

    Bug fixes

    Woah, we possibly couldn't make a release if we didn't fix some bugs!

    • Do not throw on custom stack traces (#1491) 49c16ee54fb19ea7aa77e24ac8c2b602f0aad265
    • Remove automatic content-length on ReadStream (#1510) 472b8ef9d9fc7713b740981a8b1103a7a9111b26
    • Fix promise shortcuts in case of error status code (#1543) ff918fb6dedb6d8b23421497ec890d43f45121b7 1107cc625e4cc469276483316c48896a21f6251a
    • Invert the methodRewriting option 51d88a0efed56760d116c5b911cea71e3265c787
    • Fix url not being reused on retry in rare case (#1487) 462bc630015064fa4ad4358cf28d24f95e1c958b
    • Fix hanging promise on HTTP/2 timeout (#1492) a59fac415ac013a48b1d514837628a5cf81d6878
    • Prevent uncaught ParseErrors on initial successful response (#1527) 77df9c33db5ba3126f54317171e1cfcfceefc3d5
    • Throw an error when retrying with consumed body (#1507) 62305d77d3428b5c714d21b4bbee68cc75b5f787
    • Fix a Node.js 16 bug that hangs Got streams 06a2d3d7d8d4fcc6898b6364d1a18ca1d407092b
    • Fix default pagination handling for empty Link header (#1768) 1e1e50647e93d038a4cc6a9bbbfbf61165d8fd39
    • Fix incorrect response.complete when using cache 9e15d887da3b065940bbc8ca38f9c748a0bbc75e
    • Fix Cannot call end error when request returns a Writable 226cc3995f6e16938163ebde24d8762e7dcd15e2
    • Fix Request options not being reused on retry 3c23eea5a096f6f8ea0edf3e2a27e1caca88acf9
    • Fix types being not compatible with CommonJS 3c23eea5a096f6f8ea0edf3e2a27e1caca88acf9
    • Fix got.paginate does not call init hooks (#1574) 3c23eea5a096f6f8ea0edf3e2a27e1caca88acf9
    • Generate a new object when passing options to the native https module (#1567) 3c23eea5a096f6f8ea0edf3e2a27e1caca88acf9

    Improvements

    • Make the context option mergeable (#1459) 2b8ed1f5a185f30603d24e2ceb8181782de3bc5a
    • Add generic argument to AfterResponseHook TypeScript type (#1589) 6fc04a9b92f07b07b9fba010f2231a90082a039b
    • Add read timeout (#1518) e9436720fcb32b77d39d5477b420b18083e41c02 (blocked by https://github.com/nodejs/node/issues/35923)
    • Improve the pagination API (#1644) 2675046a83c7f03613f553a8da2912d491be900d
    • Change the stackAllItems option to be false by default (#1645) 1120370e05fd8d9e768677d8474d0c82cf91a6a6
    • Throw when afterResponse hook returns an invalid value 4f21eb3db705c90797ef8ee1503704f78fea3c1b
    • Add retry.backoffLimit option 41c4136632b9391adb3ac53332b312089bc4dc16
    • Add noise retry option e83007704670b5f567ca338c156441f6c569ecb5
    • Enable more HTTPS options 83575d590a119027d319bd9208681973087564a9 fe723a0477dc02785a0b477e3d5f85d0233e5b84 (thanks @Giotino)
    • Define error.code f27e8d331627074e76e4a9ec85a2c8d0a0625e5f
    • Set options.url even if some options are invalid 8d6a6807883323a83ea5f126ca56b55d9ce5f299
    • Improve memory usage when merging options 2db5ec5d366efbbf9e0838eabfa6be774a0518a0
    • Support async generators as body 854430f01350811fe8a0ccf20cd820aabfbd3926 3df52f38edbadb45158c37d499817bc5486989c6
    • Add missing once types for Stream API 3c23eea5a096f6f8ea0edf3e2a27e1caca88acf9
    • New error type: RetryError which always triggers a new retry when thrown 3c23eea5a096f6f8ea0edf3e2a27e1caca88acf9
    • error.options is now enumerable 3c23eea5a096f6f8ea0edf3e2a27e1caca88acf9
    • defaults.handlers don't need a default handler now 3c23eea5a096f6f8ea0edf3e2a27e1caca88acf9
    • Add a parser for the Link header 3c23eea5a096f6f8ea0edf3e2a27e1caca88acf9

    Breaking changes

    Improved option normalization

    • Got exports an Option class that is specifically designed to parse and validate Got options. It is made of setters and getters that provide fast normalization and more consistent behavior.

    When passing an option does not exist, Got will throw an error. In order to retrieve the options before the error, use error.options.

    import got from 'got';
    
    try {
        await got('https://httpbin.org/anything', {
            thisOptionDoesNotExist: true
        });
    } catch (error) {
        console.error(error);
        console.error(error.options.url.href);
        // Unexpected option: thisOptionDoesNotExist
        // https://httpbin.org/anything
    }
    
    • The init hook now accepts a second argument: self, which points to an Options instance.

    In order to define your own options, you have to move them to options.context in an init hook or store them in options.context directly.

    • The init hooks are ran only when passing an options object explicitly.
    - await got('https://example.com'); // this will *not* trigger the init hooks
    + await got('https://example.com', {}); // this *will** trigger init hooks
    
    - got.defaults.options = got.mergeOptions(got.defaults.options, {…});
    + got.defaults.options.merge(…);
    

    This fixes issues like #1450

    • Legacy Url instances are not supported anymore. You need to use WHATWG URL instead.
    - await got(string, {port: 8443});
    + const url = new URL(string);
    + url.port = 8443;
    + await got(url);
    
    • No implicit timeout declaration.
    - await got('https://example.com', {timeout: 5000})
    + await got('https://example.com', {timeout: {request: 5000})
    
    • No implicit retry declaration.
    - await got('https://example.com', {retry: 5})
    + await got('https://example.com', {retry: {limit: 5})
    
    • dnsLookupIpVersion is now a number (4 or 6) or undefined
    - await got('https://example.com', {dnsLookupIpVersion: 'ipv4'})
    + await got('https://example.com', {dnsLookupIpVersion: 4})
    
    • redirectUrls and requestUrl now give URL instances
    - request.requestUrl
    + request.requestUrl.origin
    + request.requestUrl.href
    + request.requestUrl.toString()
    
    - request.redirectUrls[0]
    + request.redirectUrls[0].origin
    + request.redirectUrls[0].href
    + request.redirectUrls[0].toString()
    
    • Renamed request.aborted to request.isAborted
    - request.aborted
    + request.isAborted
    

    Reason: consistency with options.isStream.

    • Renamed the lookup option to dnsLookup
    - await got('https://example.com', {lookup: cacheable.lookup})
    + await got('https://example.com', {dnsLookup: cacheable.lookup})
    
    • The beforeRetry hook now accepts only two arguments: error and retryCount
    await got('https://example.com', {
        hooks: {
            beforeRetry: [
    -            (options, error, retryCount) => {
    -                console.log(options, error, retryCount);
    -            }
    +            (error, retryCount) => {
    +                console.log(error.options, error, retryCount);
    +            }
            ]
        }
    })
    

    The options argument has been removed, however it's still accessible via error.options. All modifications on error.options will be reflected in the next requests (no behavior change, same as with Got 11).

    • The beforeRedirect hook's first argument (options) is now a cloned instance of the Request options.

    This was done to make retrieving the original options possible: plainResponse.request.options.

    await got('http://szmarczak.com', {
        hooks: {
            beforeRedirect: [
                (options, response) => {
    -                console.log(options === response.request.options); //=> true [invalid! our original options were overriden]
    +                console.log(options === response.request.options); //=> false [we can access the original options now]
                }
            ]
        }
    })
    
    • The redirect event now takes two arguments in this order: updatedOptions and plainResponse.
    - stream.on('redirect', (response, options) => …)
    + stream.on('redirect', (options, response) => …)
    

    Reason: consistency with the beforeRedirect hook.

    • The socketPath option has been removed. Use the unix: protocol instead.
    - got('/containers/json', {socketPath: '/var/run/docker.sock'})
    + got('unix:/var/run/docker.sock:/containers/json')
    + got('http://unix:/var/run/docker.sock:/containers/json')
    
    • The retryWithMergedOptions function in an afterResponse hook no longer returns a Promise.

    It now throws RetryError, so this should this should be the last function being executed. This was done to allow beforeRetry hooks getting called.

    • You can no longer set options.agent to false. To do so, you need to define all the options.agent properties: http, https and http2.
    await got('https://example.com', {
    -    agent: false
    +    agent: {
    +        http: false,
    +        https: false,
    +        http2: false
    +    }
    })
    
    • When passing a url option when paginating, it now needs to be an absolute URL - the prefixUrl option is always reset from now on. The same when retrying in an afterResponse hook.
    - return {url: '/location'};
    + return {url: new URL('/location', response.request.options.url)};
    

    There was confusion around the prefixUrl option. It was counterintuitive if used with the Pagination API. For example, it worked fine if the server replied with a relative URL, but if it was an absolute URL then the prefixUrl would end up duplicated. In order to fix this, Got now requires an absolute URL - no prefixUrl will be applied.

    • got.extend(…) will throw when passing some options that don't accept undefined - undefined no longer retains the old value, as setting undefined explicitly may reset the option

    Documentation

    We have redesigned the documentation so it's easier to navigate and find exactly what you are looking for. We hope you like it :heart:

    Note:

    • The TypeScript documentation hasn't been updated yet. It will be updated on a stable release.
    Source code(tar.gz)
    Source code(zip)
  • v11.8.2(Feb 26, 2021)

    • Make the dnsCache option lazy (#1529) 3bd245f This slightly improves Got startup performance and fixes an issue with Jest.

    https://github.com/sindresorhus/got/compare/v11.8.1...v11.8.2

    Source code(tar.gz)
    Source code(zip)
  • v11.8.1(Dec 10, 2020)

  • v11.8.0(Oct 20, 2020)

    • Fix for sending files with size 0 on stat (#1488) 7acd380
    • beforeRetry allows stream body if different from original (#1501) 3dd2273
    • Set default value for an options object (#1495) 390b145

    https://github.com/sindresorhus/got/compare/v11.7.0...v11.8.0

    Source code(tar.gz)
    Source code(zip)
  • v11.7.0(Sep 18, 2020)

    Improvements

    • Add pfx HTTPS option (#1364) c33df7f
    • Update body after beforeRequest (#1453) e1c1844
    • Don't allocate buffer twice (#1403) 7bc69d9

    Fixes

    • Fix a regression where body was sent after redirect 88b32ea
    • Fix destructure error on promise.json() c97ce7c
    • Do not ignore userinfo on a redirect to the same origin 52de13b

    https://github.com/sindresorhus/got/compare/v11.6.2...v11.7.0

    Source code(tar.gz)
    Source code(zip)
  • v11.6.2(Sep 10, 2020)

    Bug fixes

    • Inherit the prefixUrl option from parent if it's undefined (#1448) a3da70a78aeb7f44dd3e0d0fa47cebe9541eb91e
    • Prepare a fix for hanging promise on Node.js 14.10.x 29d4e325b110ccf7571d4265d40760be4175f7ff
    • Prepare for Node.js 15.0.0 c126ff19c4e893975cbf6c2c8bebce6ed7631276

    Docs

    • Point travis-ci.org badge to travis-ci.com (#1442) 2b352d3f9e216e116efc0249a3a78b8d4492f97c
    • Clarify the retry mechanism f2486180207dba30624901761a457694096441c1
    • Fix RequestError links 3ed4af605ca6493c080cc8003a55c3b37988efee

    Tests

    • Downgrade Travis CI Node.js version to 14.9.0 (#1454) 27470b53e1bcd6f435fc77006c9e3e864961dbec
    Source code(tar.gz)
    Source code(zip)
  • v11.6.1(Sep 8, 2020)

    Fixes

    • Fix options.port on redirect (#1439) 408e22a

    Meta

    • Welcome @Giotino as a maintainer πŸŽ‰ 5031843
    • Showcase companies using Got (#1432) d12d6af

    https://github.com/sindresorhus/got/compare/v11.6.0...v11.6.1

    Source code(tar.gz)
    Source code(zip)
  • v11.6.0(Sep 2, 2020)

    Improvements

    • Add retry stream event (#1384) 707219825b2f8ff3df597230a53244636df21642
    • Add types for http-cache-semantics options 2e2295fba63c260d347fef2081cdbcae45fa6116
    • Make CancelError inherit RequestError 1f132e88b4e9b295631637757d64307032a4e56e
    • Add retryAfter to RetryObject 643a305b4d710042d2a958a21e7637183713505c
    • Add documentation comments to exported TypeScript types (#1278) eaf1e02b21e4b8c08197c6400844d4098828ecf4
    • Move cache options into a cacheOptions property 9c16d9083019fcb28f566659106036faa4839447

    Bug fixes

    • Got promise shouldn't retry when the body is a stream 6e1aeaedb5dfe4f4b15eecf72a80303c30df22af

    Docs

    • Add an example of nock integration with retrying f7bbc3753779e14b22d7aa337764c7048aebb915
    • Fix CancelError docs 28c400f4df5f45990f80641a794a2d09439bef93
    • Fix retry delay function in the README (#1425) 38bbb04ea24f01eed6f01e394bc3e9405df8cfc5
    Source code(tar.gz)
    Source code(zip)
  • v11.5.2(Aug 6, 2020)

    Docs

    • Add hpagent to proxy section (#1363) a3e171c4d43c8bbb236ef3a04feb25ba6fdf6c49
    • Mention header lowercasing inrequest migration guide (#1387) a748343363ecb0347897264fb49df4a8f4793997
    • Fixed deprecationWarning on https options (#1391) 9a309bdbe7e2552c5bffbea253d58c39d6e6c3e3

    Bug fixes

    • Fix duplicated hooks when paginating e02845f1aa737d55dce23381d0f4f2a61b1eb5e1
    • Fix dnsCache: true having no effect 043c9501b85172e09819d44ac8eb49c574b27bda
    Source code(tar.gz)
    Source code(zip)
Owner
Sindre Sorhus
Full-Time Open-Sourcerer. Wants more empathy & kindness in open source. Focuses on Swift & JavaScript. Makes macOS apps, CLI tools, npm packages. Likes unicorns
Sindre Sorhus
🏊🏾 Simplified HTTP request client.

Deprecated! As of Feb 11th 2020, request is fully deprecated. No new changes are expected to land. In fact, none have landed for some time. For more i

request 25.6k Jan 4, 2023
Node.js web server framework for Http/1.1 or Http/2

Node.js web server framework for Http/1.1 or Http/2 Description: This is http framework, you can use it to create Http/1.1 or Http/2 service。 Now let'

Jeremy Yu 10 Mar 24, 2022
Very very very powerful, extensible http client for both node.js and browser.

ES-Fetch-API δΈ­ζ–‡ | English Very very very powerful, extensible http client for both node.js and browser. Why should you use ES-Fetch API? Still using a

null 17 Dec 12, 2022
A tiny Node.js module for retrieving a request's Details (ip,os,browser)

request-details A tiny Node.js module for retrieving a request's Details (ip,os,browser) ⌨️ Installation npm install request-details βš™οΈ Usage const Re

sajjad MrX 14 Aug 20, 2022
HTTP server mocking and expectations library for Node.js

Nock HTTP server mocking and expectations library for Node.js Nock can be used to test modules that perform HTTP requests in isolation. For instance,

Nock 11.9k Jan 3, 2023
A jQuery plugin for make your ajax request's error and success messages auto handled.

sweetAjax A jQuery plugin for make your ajax request's error and success messages auto handled. Installation sweetAjax plugin has built on jQuery-ui w

Eren Sertkaya 2 May 17, 2022
✍️ Forever Diary Testimonial Request Script

✍️ Forever Diary Testimonial Request Script ❓ Why? For people like Nauty who have too many people to send Testimonial Requests to :') ??️ How to use?

Jonathan Samuel J 2 Jan 26, 2022
Promise based HTTP client for the browser and node.js

axios Promise based HTTP client for the browser and node.js New axios docs website: click here Table of Contents Features Browser Support Installing E

axios 98k Dec 31, 2022
Ajax for Node.js and browsers (JS HTTP client)

superagent Small progressive client-side HTTP request library, and Node.js module with the same API, supporting many high-level HTTP client features T

Sloth 16.2k Jan 1, 2023
Full-featured, middleware-oriented, programmatic HTTP and WebSocket proxy for node.js

rocky A multipurpose, full-featured, middleware-oriented and hackable HTTP/S and WebSocket proxy with powerful built-in features such as versatile rou

Tom 370 Nov 24, 2022
A full-featured http proxy for node.js

node-http-proxy node-http-proxy is an HTTP programmable proxying library that supports websockets. It is suitable for implementing components such as

http ... PARTY! 13.1k Jan 3, 2023
Run HTTP over UDP with Node.js

nodejs-httpp - Run HTTP over UDP based transport and Bring Web in Peer or P2P styles main js modules: udt.js, httpp.js, udts.js and httpps.js, that's

AppNet.Link 142 Aug 2, 2022
Library agnostic in-process recording of http(s) requests and responses

@gr2m/http-recorder Library agnostic in-process recording of http(s) requests and responses Install npm install @gr2m/http-recorder Usage import http

Gregor Martynus 4 May 12, 2022
make streaming http requests

hyperquest treat http requests as a streaming transport The hyperquest api is a subset of request. This module works in the browser with browserify. r

James Halliday 711 Sep 8, 2022
HTTP Client Utilities

@hapi/wreck HTTP client utilities. wreck is part of the hapi ecosystem and was designed to work seamlessly with the hapi web framework and its other c

hapi.js 383 Nov 1, 2022
Wrap native HTTP requests with RFC compliant cache support

cacheable-request Wrap native HTTP requests with RFC compliant cache support RFC 7234 compliant HTTP caching for native Node.js HTTP/HTTPS requests. C

Luke Childs 259 Dec 20, 2022
Global HTTP/HTTPS proxy agent configurable using environment variables.

global-agent Global HTTP/HTTPS proxy configurable using environment variables. Usage Setup proxy using global-agent/bootstrap Setup proxy using bootst

Gajus Kuizinas 267 Dec 20, 2022
An HTTP Web Server for Chrome (chrome.sockets API)

An HTTP Web Server for Chrome (chrome.sockets API)

Kyle Graehl 1.2k Dec 31, 2022
HTTP Client for Visual Studio Code to POST JSON, XML, image, ... files to REST APIs

friflo POST Goal Main goal of this extension is storing all HTTP request & response data automatically as files in a VSCode workspace. This ensures th

Ullrich Praetz 2 Nov 18, 2021