npm / ky
ky
What changed in ky 1 to 2, from its official release notes, upgrade guides and advisories. Sources checked 2026-10-17.
12 breaking1 security17 new APIs and options6 behavior and defaults33 fixes and other
See which of these apply to your code, ranked, in your agent:
npx @unstale/cli initky 254 changes
Breaking changes 12
Invalid options and errors thrown by init hooks now reject the returned promise instead of throwing synchronously.
Invalid options now throw a TypeError naming the option instead of being silently ignored or failing later with an internal error.
In init hooks, header names are now lowercase, so read and delete headers using lowercase names.
Malformed HTTP URLs are rejected when using baseUrl.
Hook errors are fatal outside retry handling.
All hooks now receive a single state object instead of separate arguments; the beforeError state also includes request and options.
Calling .json() on an empty body or a 204 response now throws a parse error instead of returning an empty string.
Ky now requires Node.js 22.
Ky-specific properties are no longer present on the normalized options object passed to hooks.
Renames prefixUrl to prefix and allows leading slashes in input; prefix joins strings rather than resolving URLs.
The option is renamed to prefix.
Query parameters now merge with those in the input URL instead of replacing them.
Security 1
Hardens retry behavior.
New APIs and options 12
Hooks can return
{options: {...}}to change options such as timeout, fetch, or progress callbacks for subsequent attempts.Limits the response body size in bytes after decompression; exceeding the limit throws a ResponseSizeError.
Upload progress and streamed Request bodies are supported in Bun and Deno.
A response body exceeding maxResponseSize throws this new error.
Adds support for the QUERY method.
Adds standard URL resolution: leading-slash paths resolve from the origin root, while other paths resolve relative to the base path.
Adds a data property containing the automatically consumed and pre-parsed response body, making error details immediately available.
Adds the init hook.
Adds Standard Schema validation support for .json().
Adds the NetworkError class and tightens retry logic.
Adds a helper for .extend().
Adds an overall timeout that applies across all retries.
Behavior and default changes 3
beforeError hooks now run for errors thrown while reading the response body; a dropped connection during body reading is reported as a NetworkError.
The hook now receives all error types, not only HTTPError, in its state object.
The parseJson option now receives request and response context.
Fixes and other changes 26
Aborts and timeouts cancel requests returned from hooks, interrupt pending hooks and body reads, avoid being reported as NetworkError and retried in Chromium, and enforce totalTimeout when a response or body arrives after the deadline.
Option merging preserves class instances, matches header names case-insensitively, and prevents changes in extend callbacks and init hooks from leaking into other requests.
Setting fetch to window.fetch no longer throws “Illegal invocation” in browsers.
isTimeoutError() and other type guards no longer match unrelated errors that share the same name.
Progress events now report the correct totalBytes for compressed responses and include response properties.
Using onUploadProgress no longer breaks uploads without request stream support or keepalive and no-cors requests.
parseJson is no longer ignored by response.clone().json() or when using onDownloadProgress.
Edge cases in replaceOption() are fixed.
The request property on Ky errors now refers to the request that was sent instead of an internal clone.
When retry.shouldRetry returns true, Ky respects Retry-After and rate-limit headers.
Using searchParams with a Request input no longer drops its body or options such as credentials.
Types accept readonly arrays and explicit undefined for all options, allow custom error names, and correct the .clone() and .bytes() return types.
Fixes extend() dropping a numeric retry limit when merging with an object.
Allows parseJson to handle empty response bodies.
Fixes progress callbacks for requests and responses with empty bodies.
Improves handling of the Retry-After header.
Fixes handling of Safari errors with domains.
Fixes signal replacement when extending instances.
Prevents tuple searchParams mutations from leaking across init-hook requests.
Fixes URLSearchParams deletions in the init hook.
Improves compatibility with custom fetch implementations.
Fixes forwarding of fetch options.
Non-Error values returned by beforeError hooks are ignored.
The hook is no longer skipped when it returns a Request.
Opaque responses from no-cors requests no longer cause an HTTPError.
Unsupported request streams are now handled by gracefully ignoring onUploadProgress.
ky 115 changes
New APIs and options 5
Add ky.retry() to force retries from afterResponse hooks.
Adds the context option.
Adds the retry.jitter option.
Adds the retry.retryOnTimeout option.
Adds the retry.shouldRetry option.
Behavior and default changes 3
The type guard now includes ForceRetryError.
The throwHttpErrors option can now be a function.
beforeRetry hooks can now return a Request or Response.
Fixes and other changes 7
Fixes an empty context object being added to a merged json body.
Avoids awaiting response cancellation when a retry is forced.
Fixes response body cleanup after hooks run.
Fixes handling of uppercase retry.methods values and improves their typing.
Handles backoffLimit being undefined.
Fixes support for the next option in the Next.js edge runtime.
Fixes compatibility with a non-standard Retry-After header.