ky
- Version 2.0.2
- Published
- 405 kB
- No dependencies
- MIT license
Install
npm i kyyarn add kypnpm add kyOverview
Tiny and elegant HTTP client based on the Fetch API
Index
Variables
Functions
Classes
Interfaces
Type Aliases
- AfterResponseHook
- AfterResponseState
- BeforeErrorHook
- BeforeErrorState
- BeforeRequestHook
- BeforeRequestState
- BeforeRetryHook
- BeforeRetryState
- Hooks
- InitHook
- Input
- KyInstance
- KyRequest
- KyResponse
- Progress
- ResponsePromise
- RetryOptions
- SearchParamsOption
- ShouldRetryState
- StandardSchemaV1
- StandardSchemaV1InferOutput
- StandardSchemaV1Issue
Variables
variable ky
const ky: KyInstance;Functions
function isForceRetryError
isForceRetryError: (error: unknown) => error is ForceRetryError;Type guard to check if an error is a
ForceRetryError.Parameter error
The error to check
Returns
trueif the error is aForceRetryError,falseotherwiseExample 1
import ky, {isForceRetryError} from 'ky';const api = ky.extend({hooks: {beforeRetry: [({error, retryCount}) => {if (isForceRetryError(error)) {console.log(`Forced retry #${retryCount}: ${error.code}`);}}]}});
function isHTTPError
isHTTPError: <T = unknown>(error: unknown) => error is HTTPError<T>;Type guard to check if an error is an
HTTPError.Parameter error
The error to check
Returns
trueif the error is anHTTPError,falseotherwiseExample 1
import ky, {isHTTPError} from 'ky';try {const response = await ky.get('/api/data');} catch (error) {if (isHTTPError(error)) {console.log('HTTP error status:', error.response.status);}}
function isKyError
isKyError: (error: unknown) => error is KyError;Type guard to check if an error is a
KyError.Note:
SchemaValidationErroris intentionally not considered a Ky error.KyErrorcovers failures in Ky's HTTP lifecycle (bad status, timeout, retry), while schema validation errors originate from the user-provided schema, not from Ky itself.Parameter error
The error to check
Returns
trueif the error is a Ky error,falseotherwiseExample 1
import ky, {isKyError} from 'ky';try {const response = await ky.get('/api/data');} catch (error) {if (isKyError(error)) {// Handle Ky-specific errorsconsole.log('Ky error occurred:', error.message);} else {// Handle other errorsconsole.log('Unknown error:', error);}}
function isNetworkError
isNetworkError: (error: unknown) => error is NetworkError;Type guard to check if an error is a
NetworkError.Parameter error
The error to check
Returns
trueif the error is aNetworkError,falseotherwiseExample 1
import ky, {isNetworkError} from 'ky';try {const response = await ky.get('/api/data');} catch (error) {if (isNetworkError(error)) {console.log('Network error:', error.request.url);}}
function isTimeoutError
isTimeoutError: (error: unknown) => error is TimeoutError;Type guard to check if an error is a
TimeoutError.Parameter error
The error to check
Returns
trueif the error is aTimeoutError,falseotherwiseExample 1
import ky, {isTimeoutError} from 'ky';try {const response = await ky.get('/api/data', { timeout: 1000 });} catch (error) {if (isTimeoutError(error)) {console.log('Request timed out:', error.request.url);}}
function replaceOption
replaceOption: <T>(value: T) => T;Wraps a value so that
ky.extend()will replace the parent value instead of merging with it. Works with hooks, headers, search parameters, context, and any other deep-merged option.By default,
.extend()deep-merges options with the parent instance: hooks get appended, headers get merged, and search parameters get accumulated. UsereplaceOptionwhen you want to fully replace a merged property instead.Example 1
import ky, {replaceOption} from 'ky';const base = ky.create({hooks: {beforeRequest: [addAuth, addTracking]},});// Replaces instead of appendingconst extended = base.extend({hooks: replaceOption({beforeRequest: [onlyThis]}),});// hooks.beforeRequest is now [onlyThis], not [addAuth, addTracking, onlyThis]
Classes
class ForceRetryError
class ForceRetryError extends KyError {}Error used to signal a forced retry from
afterResponsehooks.This is thrown when
ky.retry()is returned from anafterResponsehook. It is observable inbeforeRetryandbeforeErrorhooks via theisForceRetryError()type guard.
constructor
constructor(options?: ForceRetryOptions);property code
code: string;property customDelay
customDelay: number;property customRequest
customRequest: Request;property name
name: string;class HTTPError
class HTTPError<T = unknown> extends KyError {}Error thrown when the response has a non-2xx status code and
throwHttpErrorsis enabled.The error has a
responseproperty with theResponseobject, arequestproperty with theRequestobject, anoptionsproperty with the normalized options (either passed tokywhen creating an instance withky.create()or directly when performing the request), and adataproperty with the pre-parsed response body. For JSON responses (based onContent-Type), the body is parsed using theparseJsonoption if set, orJSON.parseby default. For other content types, it is set as plain text. If the body is empty or parsing fails,datawill beundefined. To avoid hanging or excessive buffering,error.datapopulation is bounded by the request timeout and a 10 MiB response body size limit. Thedataproperty is populated beforebeforeErrorhooks run, so hooks can access it.The response body is automatically consumed when populating
error.data, soerror.response.json()and other body methods will not work. Useerror.datainstead. Theerror.responseobject is still available for headers, status, etc.Be aware that some types of errors, such as network errors, inherently mean that a response was not received. In that case, the error will be an instance of
NetworkErrorinstead ofHTTPErrorand will not contain aresponseproperty.
class KyError
class KyError extends Error {}Base class for all Ky-specific errors.
HTTPError,NetworkError,TimeoutError, andForceRetryErrorextend this class.You can use
instanceof KyErrorto check if an error originated from Ky, or use theisKyError()type guard for cross-realm compatibility and TypeScript type narrowing.Note:
SchemaValidationErroris intentionally not considered a Ky error.KyErrorcovers failures in Ky's HTTP lifecycle (bad status, timeout, retry), while schema validation errors originate from the user-provided schema, not from Ky itself.
class NetworkError
class NetworkError extends KyError {}Error thrown when a network error occurs during the request (e.g., DNS failure, connection refused, offline). It has a
requestproperty with theRequestobject. The original error is available via the standardcauseproperty.Network errors are automatically retried (for retriable methods).
Note: Network errors are detected using runtime-specific heuristics. Unrecognized runtimes may produce errors that are not wrapped in
NetworkError. Use theshouldRetryoption to handle such cases.
constructor
constructor(request: Request, options?: { cause?: Error });property name
name: string;property request
request: KyRequest<unknown>;class SchemaValidationError
class SchemaValidationError extends Error {}The error thrown when [Standard Schema](https://github.com/standard-schema/standard-schema) validation fails in
.json(schema). It has anissuesproperty with the validation issues from the schema.This error intentionally does not extend
KyErrorbecause it does not represent a failure in Ky's HTTP lifecycle. The request succeeded; the user's schema rejected the data. As such, it is not matched byisKyError().Example 1
import ky, {SchemaValidationError} from 'ky';import {z} from 'zod';const userSchema = z.object({name: z.string()});try {const user = await ky('/api/user').json(userSchema);console.log(user.name);} catch (error) {if (error instanceof SchemaValidationError) {console.error(error.issues);}}
constructor
constructor(issues: readonly StandardSchemaV1Issue[]);property issues
readonly issues: readonly StandardSchemaV1Issue[];property name
name: string;class TimeoutError
class TimeoutError extends KyError {}Error thrown when the request times out. It has a
requestproperty with theRequestobject.
constructor
constructor(request: Request);property name
name: string;property request
request: KyRequest<unknown>;Interfaces
interface NormalizedOptions
interface NormalizedOptions extends RequestInit {}Normalized options passed to the
fetchcall and hooks.
property baseUrl
baseUrl?: Options['baseUrl'];property context
context: Record<string, unknown>;property credentials
credentials?: NonNullable<RequestInit['credentials']>;property method
method: NonNullable<RequestInit['method']>;property onDownloadProgress
onDownloadProgress: Options['onDownloadProgress'];property onUploadProgress
onUploadProgress: Options['onUploadProgress'];property prefix
prefix: string;property retry
retry: RetryOptions;interface Options
interface Options extends KyOptions, Omit<RequestInit, 'headers'> {}Options are the same as
window.fetch, except for the KyOptions
property headers
headers?: KyHeadersInit;HTTP headers used to make the request.
You can pass a
Headersinstance or a plain object.You can remove a header with
.extend()by passing the header with anundefinedvalue. Passingundefinedas a string removes the header only if it comes from aHeadersinstance.Example 1
``` import ky from 'ky';
const url = 'https://sindresorhus.com';
const original = ky.create({ headers: { rainbow: 'rainbow', unicorn: 'unicorn' } });
const extended = original.extend({ headers: { rainbow: undefined } });
const response = await extended(url).json();
console.log('rainbow' in response); //=> false
console.log('unicorn' in response); //=> true ```
property method
method?: LiteralUnion<HttpMethod, string>;HTTP method used to make the request.
Internally, the standard methods (
GET,POST,PUT,PATCH,HEADandDELETE) are uppercased in order to avoid server errors due to case sensitivity.
Type Aliases
type AfterResponseHook
type AfterResponseHook = ( state: AfterResponseState) => Response | RetryMarker | void | Promise<Response | RetryMarker | void>;type AfterResponseState
type AfterResponseState = { request: KyRequest; options: NormalizedOptions; response: KyResponse; /** The number of retries attempted. `0` for the initial request, increments with each retry.
This allows you to distinguish between the initial request and retries, which is useful when you need different behavior for retries (e.g., showing a notification only on the final retry). */ retryCount: number;};type BeforeErrorHook
type BeforeErrorHook = (state: BeforeErrorState) => Error | Promise<Error>;type BeforeErrorState
type BeforeErrorState = { request: KyRequest; options: NormalizedOptions; error: Error; /** The number of retries attempted. `0` for the initial request, increments with each retry.
This allows you to distinguish between the initial request and retries, which is useful when you need different error handling based on retry attempts (e.g., showing different error messages on the final attempt). */ retryCount: number;};type BeforeRequestHook
type BeforeRequestHook = ( state: BeforeRequestState) => Request | Response | void | Promise<Request | Response | void>;type BeforeRequestState
type BeforeRequestState = { request: KyRequest; options: NormalizedOptions; /** The number of retries attempted. Always `0`, since `beforeRequest` hooks run once before retry handling begins. */ retryCount: 0;};type BeforeRetryHook
type BeforeRetryHook = ( state: BeforeRetryState) => | Request | Response | typeof stop | void | Promise<Request | Response | typeof stop | void>;type BeforeRetryState
type BeforeRetryState = { request: KyRequest; options: NormalizedOptions; error: Error; /** The number of retries attempted. Always `>= 1`, since this hook is only called during retries, not on the initial request. */ retryCount: number;};type Hooks
type Hooks = { /** This hook enables you to modify the options before they are used to construct the request. The hook function receives the mutable options object and can modify it in place. You could, for example, modify `searchParams`, `headers`, or `json` here.
Unlike other hooks, `init` hooks are synchronous. Any error thrown will propagate synchronously and will not be caught by `beforeError` hooks.
A common use case is to add a search parameter to every request:
@example ``` import ky from 'ky';
const api = ky.extend({ hooks: { init: [ options => { options.searchParams = {apiKey: getApiKey()}; }, ], }, });
const response = await api.get('https://example.com/api/users'); // URL: https://example.com/api/users?apiKey=123 ```
@default [] */ init?: InitHook[]; /** This hook enables you to modify the request right before it is sent. Ky will make no further changes to the request after this. The hook function receives a state object with the normalized request, options, and retry count. You could, for example, modify `request.headers` here.
The `retryCount` is always `0`, since `beforeRequest` hooks run once before retry handling begins.
The hook can return a [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) to replace the outgoing request (remaining hooks will still run with the updated request). It can also return a [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) to completely avoid making an HTTP request, in which case remaining `beforeRequest` hooks are skipped. This can be used to mock a request, check an internal cache, etc.
Any error thrown by `beforeRequest` hooks is treated as fatal and will not trigger Ky's retry logic.
@example ``` import ky from 'ky';
const api = ky.extend({ hooks: { beforeRequest: [ ({request}) => { request.headers.set('Authorization', 'token initial-token'); } ] } });
const response = await api.get('https://example.com/api/users'); ```
**Modifying the request URL:**
@example ``` import ky from 'ky';
const api = ky.extend({ hooks: { beforeRequest: [ ({request}) => { const url = new URL(request.url); url.searchParams.set('token', 'secret-token'); return new Request(url, request); } ] } });
const response = await api.get('https://example.com/api/users'); ```
@default [] */ beforeRequest?: BeforeRequestHook[]; /** This hook enables you to modify the request right before retry. Ky will make no further changes to the request after this. The hook function receives a state object with the normalized request, options, an error instance, and retry count. You could, for example, modify `request.headers` here.
The hook can return a [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) to replace the outgoing retry request, or return a [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) to skip the retry and use that response instead. **Note:** Returning a request or response skips remaining `beforeRetry` hooks.
**Warning:** Returned `Request` objects are used as-is. If you point one at another origin, remove any credentials you do not want forwarded.
The `retryCount` is always `>= 1`, since this hook is only called during retries, not on the initial request.
If the request received a response, the error will be of type `HTTPError`. The `Response` object will be available at `error.response`, and the pre-parsed response body will be available at `error.data`. Be aware that some types of errors, such as network errors, inherently mean that a response was not received. In that case, the error will be an instance of `NetworkError` instead of `HTTPError`.
You can prevent Ky from retrying the request by throwing an error. Ky will not handle it in any way and the error will be propagated to the request initiator. The rest of the `beforeRetry` hooks will not be called in this case. Alternatively, you can return the [`ky.stop`](#kystop) symbol to do the same thing but without propagating an error (this has some limitations, see `ky.stop` docs for details).
**Modifying headers:**
@example ``` import ky from 'ky';
const response = await ky('https://example.com', { hooks: { beforeRetry: [ async ({request, options, error, retryCount}) => { const token = await ky('https://example.com/refresh-token'); request.headers.set('Authorization', `token ${token}`); } ] } }); ```
**Modifying the request URL:**
@example ``` import ky, {isHTTPError} from 'ky';
const response = await ky('https://example.com/api', { hooks: { beforeRetry: [ ({request, error}) => { // Add query parameters based on error response if ( isHTTPError(error) && typeof error.data === 'object' && error.data !== null && 'processId' in error.data ) { const url = new URL(request.url); url.searchParams.set('processId', String(error.data.processId)); return new Request(url, request); } } ] } }); ```
**Returning a cached response:**
@example ``` import ky from 'ky';
const response = await ky('https://example.com/api', { hooks: { beforeRetry: [ ({error, retryCount}) => { // Use cached response instead of retrying if (retryCount > 1 && cachedResponse) { return cachedResponse; } } ] } }); ```
@default [] */ beforeRetry?: BeforeRetryHook[]; /** This hook enables you to modify any error right before it is thrown. The hook function receives a state object with the current request, the normalized Ky options, the error, and retry count, and should return an `Error` instance.
This hook is called for all error types, including `HTTPError`, `NetworkError`, `TimeoutError`, and `ForceRetryError` (when retry limit is exceeded via `ky.retry()`). Use type guards like `isHTTPError()`, `isNetworkError()`, or `isTimeoutError()` to handle specific error types.
The `retryCount` is `0` for the initial request and increments with each retry. This allows you to distinguish between the initial request and retries, which is useful when you need different error handling based on retry attempts (e.g., showing different error messages on the final attempt).
If a `beforeRequest` or `beforeRetry` hook returns a new `Request`, inspect `request` for the final request state. `options` remains Ky's normalized options and may not mirror every property of a replacement `Request`.
@default []
@example ``` import ky, {isHTTPError} from 'ky';
await ky('https://example.com', { hooks: { beforeError: [ ({request, options, error}) => { if (isHTTPError(error)) { if ( typeof error.data === 'object' && error.data !== null && 'message' in error.data ) { error.name = 'GitHubError'; error.message = `${String(error.data.message)} (${error.response.status})`; } }
// `request` and `options` are always available console.log(`Request to ${request.url} failed`, options.context);
return error; } ] } }); ``` */ beforeError?: BeforeErrorHook[]; /** This hook enables you to read and optionally modify the response. The hook function receives a state object with the normalized request, options, a clone of the response, and retry count. The return value of the hook function will be used by Ky as the response object if it's an instance of [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response).
You can also force a retry by returning [`ky.retry(options)`](#kyretryoptions). This is useful when you need to retry based on the response body content, even if the response has a successful status code. The retry will respect the `retry.limit` option and be observable in `beforeRetry` hooks.
**Warning:** `ky.retry({request})` uses the replacement request as-is. If it targets another origin, remove any credentials you do not want forwarded.
Any non-`ky.retry()` error thrown by `afterResponse` hooks is treated as fatal and will not trigger Ky's retry logic.
The `retryCount` is `0` for the initial request and increments with each retry. This allows you to distinguish between the initial request and retries, which is useful when you need different behavior for retries (e.g., showing a notification only on the final retry).
@default []
@example ``` import ky from 'ky';
const response = await ky('https://example.com', { hooks: { afterResponse: [ ({response}) => { // You could do something with the response, for example, logging. log(response);
// Or return a `Response` instance to overwrite the response. return new Response('A different response', {status: 200}); },
// Or retry with a fresh token on a 401 error async ({request, response, retryCount}) => { if (response.status === 401 && retryCount === 0) { // Only refresh on first 401, not on subsequent retries const {token} = await ky.post('https://example.com/auth/refresh').json();
const headers = new Headers(request.headers); headers.set('Authorization', `Bearer ${token}`);
return ky.retry({ request: new Request(request, {headers}), code: 'TOKEN_REFRESHED' }); } },
// Or force retry based on response body content async ({response}) => { if (response.status === 200) { const data = await response.json(); if (data.error?.code === 'RATE_LIMIT') { // Retry with custom delay from API response return ky.retry({ delay: data.error.retryAfter * 1000, code: 'RATE_LIMIT' }); } } },
// Or show a notification only on the last retry for 5xx errors ({options, response, retryCount}) => { if (response.status >= 500 && response.status <= 599) { if (retryCount === options.retry.limit) { showNotification('Request failed after all retries'); } } } ] } }); ``` */ afterResponse?: AfterResponseHook[];};type InitHook
type InitHook = (options: Options) => void;This hook enables you to modify the options before they are used to construct the request. The hook function receives the mutable options object and can modify it in place. You could, for example, modify
searchParams,headers, orjsonhere.Unlike other hooks,
inithooks are synchronous. Any error thrown will propagate synchronously and will not be caught bybeforeErrorhooks.Example 1
import ky from 'ky';const api = ky.extend({hooks: {init: [options => {options.searchParams = {apiKey: getApiKey()};},],},});const response = await api.get('https://example.com/api/users');// URL: https://example.com/api/users?apiKey=123
type Input
type Input = string | URL | Request;type KyInstance
type KyInstance = { /** Fetch the given `url`.
@param url - `Request` object, `URL` object, or URL string. @returns A promise with `Body` method added.
@example ``` import ky from 'ky';
const json = await ky('https://example.com', {json: {foo: true}}).json();
console.log(json); //=> `{data: '🦄'}` ``` */ <T>(url: Input, options?: Options): ResponsePromise<T>; /** Fetch the given `url` using the option `{method: 'get'}`.
@param url - `Request` object, `URL` object, or URL string. @returns A promise with `Body` methods added. */ get: <T>(url: Input, options?: Options) => ResponsePromise<T>; /** Fetch the given `url` using the option `{method: 'post'}`.
@param url - `Request` object, `URL` object, or URL string. @returns A promise with `Body` methods added. */ post: <T>(url: Input, options?: Options) => ResponsePromise<T>; /** Fetch the given `url` using the option `{method: 'put'}`.
@param url - `Request` object, `URL` object, or URL string. @returns A promise with `Body` methods added. */ put: <T>(url: Input, options?: Options) => ResponsePromise<T>; /** Fetch the given `url` using the option `{method: 'delete'}`.
@param url - `Request` object, `URL` object, or URL string. @returns A promise with `Body` methods added. */ delete: <T>(url: Input, options?: Options) => ResponsePromise<T>; /** Fetch the given `url` using the option `{method: 'patch'}`.
@param url - `Request` object, `URL` object, or URL string. @returns A promise with `Body` methods added. */ patch: <T>(url: Input, options?: Options) => ResponsePromise<T>; /** Fetch the given `url` using the option `{method: 'head'}`.
@param url - `Request` object, `URL` object, or URL string. @returns A promise with `Body` methods added. */ head: (url: Input, options?: Options) => ResponsePromise; /** Create a new Ky instance with complete new defaults, without inheriting from any parent instance.
@returns A new Ky instance. */ create: (defaultOptions?: Options) => KyInstance; /** Create a new Ky instance with some defaults overridden with your own.
In contrast to `ky.create()`, `ky.extend()` inherits defaults from its parent.
You can pass headers as a `Headers` instance or a plain object.
You can remove a header with `.extend()` by passing the header with an `undefined` value. Passing `undefined` as a string removes the header only if it comes from a `Headers` instance.
Similarly, you can remove existing `hooks` entries by extending the hook with an explicit `undefined`.
By default, `.extend()` deep-merges options: hooks are appended, headers are merged, and search parameters are accumulated. Use `replaceOption` when you want to fully replace a merged property instead.
You can also refer to parent defaults by providing a function to `.extend()`.
@example ``` import ky from 'ky';
const api = ky.create({prefix: 'https://example.com/api'});
const usersApi = api.extend((options) => ({prefix: `${options.prefix}/users`}));
const response = await usersApi.get('123'); //=> 'https://example.com/api/users/123'
const response = await api.get('version'); //=> 'https://example.com/api/version' ```
@returns A new Ky instance. */ extend: ( defaultOptions: Options | ((parentOptions: Options) => Options) ) => KyInstance; /** A `Symbol` that can be returned by a `beforeRetry` hook to stop the retry. This will also short circuit the remaining `beforeRetry` hooks.
Note: Returning this symbol makes Ky abort and return with an `undefined` response. Be sure to check for a response before accessing any properties on it or use [optional chaining](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining). It is also incompatible with body methods, such as `.json()` or `.text()`, because there is no response to parse. In general, we recommend throwing an error instead of returning this symbol, as that will cause Ky to abort and then throw, which avoids these limitations.
A valid use-case for `ky.stop` is to prevent retries when making requests for side effects, where the returned data is not important. For example, logging client activity to the server.
@example ``` import ky from 'ky';
const options = { hooks: { beforeRetry: [ async ({request, options, error, retryCount}) => { const shouldStopRetry = await ky('https://example.com/api'); if (shouldStopRetry) { return ky.stop; } } ] } };
// Note that response will be `undefined` in case `ky.stop` is returned. const response = await ky.post('https://example.com', options);
// Using `.text()` or other body methods is not supported. const text = await ky('https://example.com', options).text(); ``` */ readonly stop: typeof stop; /** Force a retry from an `afterResponse` hook.
This allows you to retry a request based on the response content, even if the response has a successful status code. The retry will respect the `retry.limit` option and skip the `shouldRetry` check. The forced retry is observable in `beforeRetry` hooks, where the error will be a `ForceRetryError`.
@example ``` import ky, {isForceRetryError} from 'ky';
const api = ky.extend({ hooks: { afterResponse: [ async ({response}) => { // Retry based on response body content if (response.status === 200) { const data = await response.json();
// Simple retry with default delay if (data.error?.code === 'TEMPORARY_ERROR') { return ky.retry(); }
// Retry with custom delay from API response if (data.error?.code === 'RATE_LIMIT') { return ky.retry({ delay: data.error.retryAfter * 1000, code: 'RATE_LIMIT' }); } } } ], beforeRetry: [ ({error, retryCount}) => { // Observable in beforeRetry hooks if (isForceRetryError(error)) { console.log(`Forced retry #${retryCount}: ${error.message}`); // Example output: "Forced retry #1: Forced retry: RATE_LIMIT" } } ] } });
const response = await api.get('https://example.com/api'); ``` */ readonly retry: typeof retry;};type KyRequest
type KyRequest<T = unknown> = { json: <J = T>() => Promise<J>;} & Request;type KyResponse
type KyResponse<T = unknown> = { json: <J = T>() => Promise<J>;} & Response;type Progress
type Progress = { /** A number between `0` and `1` representing the progress percentage. */ percent: number; /** The number of bytes transferred so far. */ transferredBytes: number; /** The total number of bytes to be transferred. This is an estimate and may be `0` if the total size cannot be determined. */ totalBytes: number;};type ResponsePromise
type ResponsePromise<T = unknown> = { arrayBuffer: () => Promise<ArrayBuffer>; blob: () => Promise<Blob>; formData: () => Promise<FormData>; /** Get the response body as raw bytes.
Note: This shortcut is only available when the runtime supports `Response.prototype.bytes()`. */ bytes: () => Promise<Uint8Array>; json: { /** Get the response body as JSON.
@example ``` import ky from 'ky';
const json = await ky(…).json(); ```
@example ``` import ky from 'ky';
interface Result { value: number; }
const result1 = await ky(…).json<Result>(); // or const result2 = await ky<Result>(…).json(); ``` */ <JsonType = T>(): Promise<JsonType>; /** Get the response body as JSON and validate it with a Standard Schema. Use a Standard Schema compatible validator (for example, Zod 3.24+).
Throws a `SchemaValidationError` when validation fails.
@example ``` import ky from 'ky'; import {z} from 'zod';
const userSchema = z.object({name: z.string()});
const user = await ky('/api/user').json(userSchema); ``` */ <Schema extends StandardSchemaV1>(schema: Schema): Promise< StandardSchemaV1InferOutput<Schema> >; }; text: () => Promise<string>;} & Promise<KyResponse<T>>;type RetryOptions
type RetryOptions = { /** The number of times to retry failed requests.
@default 2 */ limit?: number; /** The HTTP methods allowed to retry.
@default ['get', 'put', 'head', 'delete', 'options', 'trace'] */ methods?: HttpMethod[]; /** The HTTP status codes allowed to retry.
@default [408, 413, 429, 500, 502, 503, 504] */ statusCodes?: number[]; /** The HTTP status codes allowed to retry with a `Retry-After` header.
@default [413, 429, 503] */ afterStatusCodes?: number[]; /** If the `Retry-After` header is greater than `maxRetryAfter`, it will use `maxRetryAfter`.
@default Infinity */ maxRetryAfter?: number; /** The upper limit of the delay per retry in milliseconds. To clamp the delay, set `backoffLimit` to 1000, for example.
By default, the delay is calculated in the following way:
``` 0.3 * (2 ** (attemptCount - 1)) * 1000 ```
The delay increases exponentially.
@default Infinity */ backoffLimit?: number; /** A function to calculate the delay in milliseconds between retries given `attemptCount` (starts from 1).
@default attemptCount => 0.3 * (2 ** (attemptCount - 1)) * 1000 */ delay?: (attemptCount: number) => number; /** Add random jitter to retry delays to prevent thundering herd problems.
When many clients retry simultaneously (e.g., after hitting a rate limit), they can overwhelm the server again. Jitter adds randomness to break this synchronization.
Set to `true` to use full jitter, which randomizes the delay between 0 and the computed delay.
Alternatively, pass a function to implement custom jitter strategies.
Note: Jitter is not applied when the server provides a `Retry-After` header, as the server's explicit timing should be respected.
@default undefined (no jitter)
@example ``` import ky from 'ky';
const json = await ky('https://example.com', { retry: { limit: 5,
// Full jitter (randomizes delay between 0 and computed value) jitter: true
// Percentage jitter (80-120% of delay) // jitter: delay => delay * (0.8 + Math.random() * 0.4)
// Absolute jitter (±100ms) // jitter: delay => delay + (Math.random() * 200 - 100) } }).json(); ``` */ jitter?: boolean | ((delay: number) => number) | undefined; /** Whether to retry when the request times out.
@default false
@example ``` import ky from 'ky';
const json = await ky('https://example.com', { retry: { limit: 3, retryOnTimeout: true } }).json(); ``` */ retryOnTimeout?: boolean; /** A function to determine whether a retry should be attempted.
This function takes precedence over the default retry checks (`retryOnTimeout`, status code checks, etc.) for retriable methods. It is only called after the retry limit and method checks pass.
**Note:** This is different from the `beforeRetry` hook: - `shouldRetry`: Controls WHETHER to retry (called before the retry decision is made) - `beforeRetry`: Called AFTER retry is confirmed, allowing you to modify the request
Should return: - `true` to force a retry (bypasses `retryOnTimeout`, status code checks, and other validations) - `false` to prevent a retry (no retry will occur) - `undefined` to use the default retry logic (`retryOnTimeout`, status codes, network errors). Unrecognized error types are not retried.
@default undefined
@example ``` import ky, {HTTPError} from 'ky';
const json = await ky('https://example.com', { retry: { limit: 3, shouldRetry: ({error, retryCount}) => { // Retry on specific business logic errors from API if (error instanceof HTTPError) { const status = error.response.status;
// Retry on 429 (rate limit) but only for first 2 attempts if (status === 429 && retryCount <= 2) { return true; }
// Don't retry on 4xx errors except rate limits if (status >= 400 && status < 500) { return false; } }
// Use default retry logic for other errors return undefined; } } }).json(); ``` */ shouldRetry?: ( state: ShouldRetryState ) => boolean | undefined | Promise<boolean | undefined>;};type SearchParamsOption
type SearchParamsOption = | SearchParamsInit | Record<string, string | number | boolean | undefined> | Array<Array<string | number | boolean>>;type ShouldRetryState
type ShouldRetryState = { /** The error that caused the request to fail. */ error: Error; /** The number of retries attempted. Starts at 1 for the first retry. */ retryCount: number;};type StandardSchemaV1
type StandardSchemaV1<InputType = unknown, OutputType = InputType> = { readonly '~standard': { readonly version: 1; readonly vendor: string; readonly validate: ( value: unknown, options?: StandardSchemaV1Options ) => | StandardSchemaV1Result<OutputType> | Promise<StandardSchemaV1Result<OutputType>>; readonly types?: StandardSchemaV1Types<InputType, OutputType> | undefined; };};type StandardSchemaV1InferOutput
type StandardSchemaV1InferOutput<Schema extends StandardSchemaV1> = Schema['~standard'] extends { readonly types: StandardSchemaV1Types<unknown, infer OutputType>; } ? OutputType : Extract< Awaited<ReturnType<Schema['~standard']['validate']>>, StandardSchemaV1SuccessResult<unknown> > extends StandardSchemaV1SuccessResult<infer OutputType> ? OutputType : unknown;type StandardSchemaV1Issue
type StandardSchemaV1Issue = { readonly message: string; readonly path?: | ReadonlyArray< | PropertyKey | { readonly key: PropertyKey; } > | undefined;};Package Files (17)
- distribution/errors/ForceRetryError.d.ts
- distribution/errors/HTTPError.d.ts
- distribution/errors/KyError.d.ts
- distribution/errors/NetworkError.d.ts
- distribution/errors/SchemaValidationError.d.ts
- distribution/errors/TimeoutError.d.ts
- distribution/index.d.ts
- distribution/types/ResponsePromise.d.ts
- distribution/types/hooks.d.ts
- distribution/types/ky.d.ts
- distribution/types/options.d.ts
- distribution/types/request.d.ts
- distribution/types/response.d.ts
- distribution/types/retry.d.ts
- distribution/types/standard-schema.d.ts
- distribution/utils/merge.d.ts
- distribution/utils/type-guards.d.ts
Dependencies (0)
No dependencies.
Dev Dependencies (15)
Peer Dependencies (0)
No peer dependencies.
Badge
To add a badge like this oneto your package's README, use the codes available below.
You may also use Shields.io to create a custom badge linking to https://www.jsdocs.io/package/ky.
- Markdown[](https://www.jsdocs.io/package/ky)
- HTML<a href="https://www.jsdocs.io/package/ky"><img src="https://img.shields.io/badge/jsDocs.io-reference-blue" alt="jsDocs.io"></a>
- Updated .
Package analyzed in 3887 ms. - Missing or incorrect documentation? Open an issue for this package.
