Skip to content
D
Documentation

Overview

reference
8 min readUpdated

ky

Tiny and elegant HTTP client based on the Fetch API

Install

bash
npm install ky

On their own pages

Functions

isForceRetryError

Type guard to check if an error is a ForceRetryError.

ts
function isForceRetryError(error: unknown): error is ForceRetryError

Parameters

  • error: The error to check

Returns true if the error is a ForceRetryError, false otherwise

Example

import ky, {isForceRetryError} from 'ky';

const api = ky.extend({
	hooks: {
		beforeRetry: [
			({error, retryCount}) => {
				if (isForceRetryError(error)) {
					console.log(`Forced retry #${retryCount}: ${error.code}`);
				}
			}
		]
	}
});

isHTTPError

Type guard to check if an error is an HTTPError.

ts
function isHTTPError<T = unknown>(error: unknown): error is HTTPError<T>

Parameters

  • error: The error to check

Returns true if the error is an HTTPError, false otherwise

Example

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);
	}
}

isKyError

Type guard to check if an error is a KyError.

Note: SchemaValidationError is intentionally not considered a Ky error. KyError covers failures in Ky's HTTP lifecycle (bad status, timeout, retry), while schema validation errors originate from the user-provided schema, not from Ky itself.

ts
function isKyError(error: unknown): error is KyError

Parameters

  • error: The error to check

Returns true if the error is a Ky error, false otherwise

Example

import ky, {isKyError} from 'ky';
try {
	const response = await ky.get('/api/data');
} catch (error) {
	if (isKyError(error)) {
		// Handle Ky-specific errors
		console.log('Ky error occurred:', error.message);
	} else {
		// Handle other errors
		console.log('Unknown error:', error);
	}
}

isNetworkError

Type guard to check if an error is a NetworkError.

ts
function isNetworkError(error: unknown): error is NetworkError

Parameters

  • error: The error to check

Returns true if the error is a NetworkError, false otherwise

Example

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);
	}
}

isResponseSizeError

Not released yet. It is in the source, not in the latest release on npm.

Type guard to check if an error is a ResponseSizeError.

ts
function isResponseSizeError(error: unknown): error is ResponseSizeError

Parameters

  • error: The error to check

Returns true if the error is a ResponseSizeError, false otherwise

Example

import ky, {isResponseSizeError} from 'ky';

try {
	await ky('https://example.com/data', {maxResponseSize: 1024}).json();
} catch (error) {
	if (isResponseSizeError(error)) {
		console.log(`Response exceeded ${error.maxResponseSize} bytes`);
	}
}

isTimeoutError

Type guard to check if an error is a TimeoutError.

ts
function isTimeoutError(error: unknown): error is TimeoutError

Parameters

  • error: The error to check

Returns true if the error is a TimeoutError, false otherwise

Example

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);
	}
}

Classes

ForceRetryError

Error used to signal a forced retry from afterResponse hooks.

This is thrown when ky.retry() is returned from an afterResponse hook. It is observable in beforeRetry and beforeError hooks via the isForceRetryError() type guard.

ts
class ForceRetryError extends KyError

Properties

NameTypeDefaultDescription
name'ForceRetryError'
customDelaynumber | undefined
codestring | undefined
customRequestRequest | undefined
messagestring
stack?string

Methods

  • constructor(options?: ForceRetryOptions)

KyError

Base class for all Ky-specific errors. HTTPError, NetworkError, TimeoutError, ResponseSizeError, and ForceRetryError extend this class.

You can use instanceof KyError to check if an error originated from Ky, or use the isKyError() type guard for cross-realm compatibility and TypeScript type narrowing.

Note: SchemaValidationError is intentionally not considered a Ky error. KyError covers failures in Ky's HTTP lifecycle (bad status, timeout, retry), while schema validation errors originate from the user-provided schema, not from Ky itself.

ts
class KyError extends Error

Properties

NameTypeDefaultDescription
name'KyError'
messagestring
stack?string

Methods

  • get isKyError(): true

NetworkError

Error thrown when a network error occurs during the request (e.g., DNS failure, connection refused, offline). It has a request property with the Request object. The original error is available via the standard cause property.

Network errors are automatically retried (for retriable methods). A connection that drops while a Ky shortcut method like .json() is reading the response body is also wrapped in NetworkError, but it is not retried because the response has already been received.

Note: Network errors are detected using runtime-specific heuristics. Unrecognized runtimes may produce errors that are not wrapped in NetworkError. Use the shouldRetry option to handle such cases.

ts
class NetworkError extends KyError

Properties

NameTypeDefaultDescription
name'NetworkError'
requestKyRequest
messagestring
stack?string

Methods

  • constructor(request: Request, options?: {cause?: Error | undefined})

ResponseSizeError

Not released yet. It is in the source, not in the latest release on npm.

Error thrown when the response body exceeds maxResponseSize. It has a request property with the Request object and a maxResponseSize property with the configured limit in bytes.

ts
class ResponseSizeError extends KyError

Properties

NameTypeDefaultDescription
name'ResponseSizeError'
requestKyRequest
maxResponseSizenumber
messagestring
stack?string

Methods

  • constructor(request: Request, maxResponseSize: number)

Example

import ky, {isResponseSizeError} from 'ky';

try {
	await ky('https://example.com/data', {maxResponseSize: 1024}).json();
} catch (error) {
	if (isResponseSizeError(error)) {
		console.log(`Response exceeded ${error.maxResponseSize} bytes`);
	}
}

SchemaValidationError

The error thrown when Standard Schema validation fails in .json(schema). It has an issues property with the validation issues from the schema.

This error intentionally does not extend KyError because 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 by isKyError().

ts
class SchemaValidationError extends Error

Properties

NameTypeDefaultDescription
name'SchemaValidationError'
issuesreadonly StandardSchemaV1Issue[]
messagestring
stack?string

Methods

  • constructor(issues: readonly StandardSchemaV1Issue[])

Example

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);
	}
}

TimeoutError

Error thrown when the request times out. It has a request property with the Request object.

ts
class TimeoutError extends KyError

Properties

NameTypeDefaultDescription
name'TimeoutError'
requestKyRequest
messagestring
stack?string

Methods

  • constructor(request: Request)

Constants

default

The package's default export: import it under a name of your own, import ky from 'ky'.

ts
declare const ky: KyInstance
export default ky

replaceOption

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. Use replaceOption when you want to fully replace a merged property instead.

ts
const replaceOption: <T>(value: T) => T

Example

import ky, {replaceOption} from 'ky';

const base = ky.create({
	hooks: {beforeRequest: [addAuth, addTracking]},
});

// Replaces instead of appending
const extended = base.extend({
	hooks: replaceOption({beforeRequest: [onlyThis]}),
});
// hooks.beforeRequest is now [onlyThis], not [addAuth, addTracking, onlyThis]

Types

AfterResponseHook

ts
type AfterResponseHook = (state: AfterResponseState) => Response | RetryMarker | void | Promise<Response | RetryMarker | void>;

AfterResponseState

ts
type AfterResponseState = { … }

Properties

NameTypeDefaultDescription
requestKyRequest
optionsReadonly<NormalizedOptions>
responseKyResponse
retryCountnumberThe number of retries attempted. 0 for the initial request, increments with each retry.

BeforeErrorHook

ts
type BeforeErrorHook = (state: BeforeErrorState) => Error | Promise<Error>;

BeforeErrorState

ts
type BeforeErrorState = { … }

Properties

NameTypeDefaultDescription
requestKyRequest
optionsReadonly<NormalizedOptions>
errorError
retryCountnumberThe number of retries attempted. 0 for the initial request, increments with each retry.

BeforeRequestHook

ts
type BeforeRequestHook = (state: BeforeRequestState) => Request | Response | void | Promise<Request | Response | void>;

BeforeRequestState

ts
type BeforeRequestState = { … }

Properties

NameTypeDefaultDescription
requestKyRequest
optionsReadonly<NormalizedOptions>
retryCount0The number of retries attempted. Always 0, since beforeRequest hooks run once before retry handling begins.

BeforeRetryHook

ts
type BeforeRetryHook = (state: BeforeRetryState) => Request | Response | typeof stop | void | Promise<Request | Response | typeof stop | void>;

BeforeRetryState

ts
type BeforeRetryState = { … }

Properties

NameTypeDefaultDescription
requestKyRequest
optionsReadonly<NormalizedOptions>
errorError
retryCountnumberThe number of retries attempted. Always >= 1, since this hook is only called during retries, not on the initial request.

InitHook

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. The headers option is always a plain object with lowercase names, where a header removed with undefined keeps an undefined value.

Unlike other hooks, init hooks are synchronous. Any error thrown will propagate synchronously and will not be caught by beforeError hooks.

ts
type InitHook = (options: InitOptions) => void;

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

Input

ts
type Input = string | URL | Request;

Members

  • toString(): string — Returns a string representation of a string.
  • valueOf(): string — Returns the primitive value of the specified object.

KyInstance

ts
type KyInstance = { … }

Properties

NameTypeDefaultDescription
get<T>(url: Input, options?: Options) => ResponsePromise<T>Fetch the given url using the option {method: 'get'}.
post<T>(url: Input, options?: Options) => ResponsePromise<T>Fetch the given url using the option {method: 'post'}.
put<T>(url: Input, options?: Options) => ResponsePromise<T>Fetch the given url using the option {method: 'put'}.
delete<T>(url: Input, options?: Options) => ResponsePromise<T>Fetch the given url using the option {method: 'delete'}.
patch<T>(url: Input, options?: Options) => ResponsePromise<T>Fetch the given url using the option {method: 'patch'}.
head(url: Input, options?: Options) => ResponsePromiseFetch the given url using the option {method: 'head'}.
query<T>(url: Input, options?: Options) => ResponsePromise<T>Fetch the given url using the option {method: 'query'}.
create(defaultOptions?: Options) => KyInstanceCreate a new Ky instance with complete new defaults, without inheriting from any parent instance.
extend(defaultOptions: Options | ((parentOptions: Options) => Options)) => KyInstanceCreate a new Ky instance with some defaults overridden with your own.
stoptypeof stopA Symbol that can be returned by a beforeRetry hook to stop the retry. This will also short circuit the remaining beforeRetry hooks.
retrytypeof retryForce a retry from an afterResponse hook.

KyResponse

ts
type KyResponse<T = unknown> = {
	clone: () => KyResponse<T>;
	json: <J = T>() => Promise<J>;
} & Response;

Properties

NameTypeDefaultDescription
clone() => KyResponse<T>
json<J = T>() => Promise<J>
headersHeadersThe headers read-only property of the with the response.
okbooleanThe ok read-only property of the Response interface contains a Boolean stating whether the response was successful (status in the range 200-299) or not.
redirectedbooleanThe redirected read-only property of the Response interface indicates whether or not the response is the result of a request you made which was redirected.
statusnumberThe status read-only property of the Response interface contains the HTTP status codes of the response.
statusTextstringThe statusText read-only property of the Response interface contains the status message corresponding to the HTTP status code in Response.status.
typeResponseTypeThe type read-only property of the Response interface contains the type of the response.
urlstringThe url read-only property of the Response interface contains the URL of the response.
bodyReadableStream<Uint8Array<ArrayBuffer>> | nullMDN Reference
bodyUsedbooleanMDN Reference

Members

Progress

ts
type Progress = { … }

Properties

NameTypeDefaultDescription
percentnumberA number between 0 and 1 representing the progress percentage.
transferredBytesnumberThe number of bytes transferred so far.
totalBytesnumberThe total number of bytes to be transferred. This is an estimate and may be 0 for an empty transfer or when the total size cannot be determined.

SearchParamsOption

ts
type SearchParamsOption =
	| Exclude<SearchParamsInit, string[][]>
	| Record<string, string | number | boolean | undefined>
	| Array<Array<string | number | boolean>>
	| ReadonlyArray<ReadonlyArray<string | number | boolean>>;

Members

  • toString(): string — Returns a string representation of a string.
  • valueOf(): string — Returns the primitive value of the specified object.

ShouldRetryState

ts
type ShouldRetryState = { … }

Properties

NameTypeDefaultDescription
errorErrorThe error that caused the request to fail.
retryCountnumberThe number of retries attempted. Starts at 1 for the first retry.

StandardSchemaV1

ts
type StandardSchemaV1<InputType = unknown, OutputType = InputType> = { … }

Properties

NameTypeDefaultDescription
'~standard'{ readonly version: 1; readonly vendor: string; readonly validate: ( value: unknown, options?: StandardSchemaV1Options, ) => StandardSchemaV1Result<OutputType> | Promise<StandardSchemaV1Result<OutputType>>; readonly types?: StandardSchemaV1Types<InputType, OutputType> | undefined; }
'~standard'{ readonly version: 1; readonly vendor: string; readonly validate: ( value: unknown, options?: StandardSchemaV1Options, ) => StandardSchemaV1Result<OutputType> | Promise<StandardSchemaV1Result<OutputType>>; readonly types?: StandardSchemaV1Types<InputType, OutputType> | undefined; }

StandardSchemaV1InferOutput

ts
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;

StandardSchemaV1Issue

ts
type StandardSchemaV1Issue = { … }

Properties

NameTypeDefaultDescription
messagestring
path?ReadonlyArray<PropertyKey | {readonly key: PropertyKey}> | undefined

Was this page helpful?