Breaking changes
- Require Node.js 22 b933476
- Remove promise cancel API a06ac6c
promise.cancel()is gone. Use thesignaloption withAbortControllerinstead.
- Remove
isStreamoption c241c6c- Use
got.stream()directly.
- Use
- Use native
FormDataglobal 670b228- Use the Web API
FormDataglobal directly (available in Node.js 18+).
- Use the Web API
responseType: 'buffer'returnsUint8Arrayinstead ofBuffer309e36dresponse.rawBodyandpromise.buffer()now return aUint8Array.Bufferis a subclass ofUint8Array, so most code will continue to work, but strict type checks will need updating.
strictContentLengthdefaults totrue08e9dff- Got now throws a
ContentLengthMismatchErrorby default ifContent-Lengthdoesn't match the actual body size. Set{strictContentLength: false}to restore the old behavior.
- Got now throws a
retry.enforceRetryRulesdefaults totrue9bc8dfb- Custom
calculateDelayfunctions are now only called when a retry is actually allowed bylimit,methods,statusCodes, anderrorCodes. If yourcalculateDelaywas previously used to override retry eligibility unconditionally, set{retry: {enforceRetryRules: false}}.
- Custom
- Piped header copying is now opt-in 8e392f3
- Got no longer automatically copies headers from a piped stream. Set
{copyPipedHeaders: true}to re-enable. Hop-by-hop headers are never copied even when enabled (RFC 9110 §7.6.1).
- Got no longer automatically copies headers from a piped stream. Set
urlremoved from public options objects 87de8d6- The
urlproperty is no longer present on the options object passed to hooks. Useresponse.urlorrequest.requestUrlinstead.
- The
- 300 and 304 responses are no longer auto-followed 5fccaab
- Per RFC 9110, 304 is a conditional-GET hint, not a redirect, and 300 is only a SHOULD for user agents. Got now returns these responses as-is. Handle them manually if needed.
Improvements
- Stream decode large
text/jsonbodies incrementally for lower peak memory usage c9a95b1 uploadProgressnow emits granular per-chunk events forjsonandformrequest bodies 13c889d
Migration guide
Replace promise.cancel() with AbortController
Before:
const promise = got(url);
promise.cancel();After:
const controller = new AbortController();
const promise = got(url, {signal: controller.signal});
controller.abort();Replace isStream: true with got.stream()
Before:
got(url, {isStream: true});After:
got.stream(url);Replace form-data / form-data-encoder with native FormData
Before:
import {FormData} from 'formdata-node';
// or: import {FormData} from 'formdata-polyfill/esm.min.js';
const form = new FormData();
form.set('name', 'value');
await got.post(url, {body: form});After:
const form = new FormData();
form.set('name', 'value');
await got.post(url, {body: form});Update Buffer usage to Uint8Array
response.rawBody and promise.buffer() now return Uint8Array instead of Buffer.
Before:
const data = await got(url).buffer();
const copy = Buffer.from(data);After:
const data = await got(url).buffer();
const copy = new Uint8Array(data);If you need Buffer-specific APIs, wrap with Buffer.from(data.buffer, data.byteOffset, data.byteLength).
strictContentLength is now on by default
If you send requests where the Content-Length header might not match the actual body size, opt out:
got.extend({strictContentLength: false});retry.enforceRetryRules is now on by default
If your calculateDelay function was overriding retry eligibility (e.g. retrying on methods or status codes outside the defaults), opt out:
got.extend({
retry: {
enforceRetryRules: false,
calculateDelay: ({computedValue}) => {
// computedValue is 0 when retry is not allowed
if (computedValue === 0) {
return 0;
}
return computedValue;
},
},
});Piped header copying is now opt-in
If you pipe streams into Got and rely on automatic header forwarding (e.g. Content-Type), re-enable it:
got.extend({copyPipedHeaders: true});300 and 304 responses are no longer followed
If your code depended on Got auto-following 300 Multi-Choice or handling 304 Not Modified as a redirect, you now need to handle them yourself in an afterResponse hook or check response.statusCode manually.