Tiny and elegant HTTP client based on the Fetch API
npx @tessl/cli install tessl/npm-ky@1.10.0Ky is a tiny and elegant HTTP client based on the Fetch API. It provides a simplified interface for making HTTP requests with modern features like automatic retries, JSON handling, timeout support, URL prefixing, and an extensible hooks system. Ky works seamlessly across browsers, Node.js, Bun, and Deno environments.
npm install kyimport ky from "ky";For CommonJS:
const ky = require("ky").default;import ky from "ky";
// Simple GET request
const user = await ky.get("https://api.example.com/user/123").json();
// POST with JSON data
const response = await ky.post("https://api.example.com/users", {
json: { name: "Alice", email: "alice@example.com" }
}).json();
// Request with options
const data = await ky("https://api.example.com/data", {
timeout: 5000,
retry: 3,
headers: { "Authorization": "Bearer token" }
}).json();Ky is built around several key components:
Core HTTP request methods with convenient shortcuts and full TypeScript support.
// Main request function
function ky<T>(url: Input, options?: Options): ResponsePromise<T>;
// HTTP method shortcuts
function get<T>(url: Input, options?: Options): ResponsePromise<T>;
function post<T>(url: Input, options?: Options): ResponsePromise<T>;
function put<T>(url: Input, options?: Options): ResponsePromise<T>;
function patch<T>(url: Input, options?: Options): ResponsePromise<T>;
function delete<T>(url: Input, options?: Options): ResponsePromise<T>;
function head(url: Input, options?: Options): ResponsePromise;Create and extend ky instances with custom defaults for different API endpoints or configurations.
function create(defaultOptions?: Options): KyInstance;
function extend(defaultOptions?: Options | ((parentOptions: Options) => Options)): KyInstance;Comprehensive options for customizing request behavior including JSON handling, retries, timeouts, and progress tracking.
interface Options extends KyOptions, Omit<RequestInit, 'headers'> {
method?: LiteralUnion<HttpMethod, string>;
headers?: KyHeadersInit;
}
interface KyOptions {
json?: unknown;
parseJson?: (text: string) => unknown;
stringifyJson?: (data: unknown) => string;
searchParams?: SearchParamsOption;
prefixUrl?: URL | string;
retry?: RetryOptions | number;
timeout?: number | false;
throwHttpErrors?: boolean;
onDownloadProgress?: (progress: Progress, chunk: Uint8Array) => void;
onUploadProgress?: (progress: Progress, chunk: Uint8Array) => void;
fetch?: (input: Input, init?: RequestInit) => Promise<Response>;
hooks?: Hooks;
}Enhanced response promises with body method shortcuts and automatic error handling for non-2xx status codes.
interface ResponsePromise<T = unknown> extends Promise<KyResponse<T>> {
arrayBuffer(): Promise<ArrayBuffer>;
blob(): Promise<Blob>;
formData(): Promise<FormData>;
bytes(): Promise<Uint8Array>;
json<J = T>(): Promise<J>;
text(): Promise<string>;
}Configurable retry logic with exponential backoff, status code filtering, and Retry-After header support.
interface RetryOptions {
limit?: number;
methods?: string[];
statusCodes?: number[];
afterStatusCodes?: number[];
maxRetryAfter?: number;
backoffLimit?: number;
delay?: (attemptCount: number) => number;
}Extensible lifecycle hooks for request modification, response processing, error handling, and retry customization.
interface Hooks {
beforeRequest?: BeforeRequestHook[];
beforeRetry?: BeforeRetryHook[];
afterResponse?: AfterResponseHook[];
beforeError?: BeforeErrorHook[];
}Comprehensive error handling with detailed HTTP and timeout error classes containing request and response information.
class HTTPError<T = unknown> extends Error {
response: KyResponse<T>;
request: KyRequest;
options: NormalizedOptions;
}
class TimeoutError extends Error {
request: KyRequest;
}Core type definitions used throughout the Ky API:
interface NormalizedOptions extends RequestInit {
method: NonNullable<RequestInit['method']>;
credentials?: NonNullable<RequestInit['credentials']>;
retry: RetryOptions;
prefixUrl: string;
onDownloadProgress: Options['onDownloadProgress'];
onUploadProgress: Options['onUploadProgress'];
}
type Input = string | URL | Request;
type KyInstance = {
<T>(url: Input, options?: Options): ResponsePromise<T>;
get: <T>(url: Input, options?: Options) => ResponsePromise<T>;
post: <T>(url: Input, options?: Options) => ResponsePromise<T>;
put: <T>(url: Input, options?: Options) => ResponsePromise<T>;
patch: <T>(url: Input, options?: Options) => ResponsePromise<T>;
delete: <T>(url: Input, options?: Options) => ResponsePromise<T>;
head: (url: Input, options?: Options) => ResponsePromise;
create: (defaultOptions?: Options) => KyInstance;
extend: (defaultOptions?: Options | ((parentOptions: Options) => Options)) => KyInstance;
readonly stop: typeof stop;
};
interface KyRequest<T = unknown> extends Request {
json: <J = T>() => Promise<J>;
}
interface KyResponse<T = unknown> extends Response {
json: <J = T>() => Promise<J>;
}
interface Progress {
percent: number;
transferredBytes: number;
totalBytes: number;
}
type SearchParamsInit = string | string[][] | Record<string, string> | URLSearchParams | undefined;
type SearchParamsOption = SearchParamsInit | Record<string, string | number | boolean | undefined> | Array<Array<string | number | boolean>>;
type KyHeadersInit = NonNullable<RequestInit['headers']> | Record<string, string | undefined>;
type LiteralUnion<LiteralType, BaseType extends string> = LiteralType | (BaseType & Record<never, never>);
type HttpMethod = 'get' | 'post' | 'put' | 'patch' | 'head' | 'delete';
type BeforeRequestHook = (
request: KyRequest,
options: NormalizedOptions
) => Request | Response | void | Promise<Request | Response | void>;
type BeforeRetryState = {
request: KyRequest;
options: NormalizedOptions;
error: Error;
retryCount: number;
};
type BeforeRetryHook = (options: BeforeRetryState) => typeof stop | void | Promise<typeof stop | void>;
type AfterResponseHook = (
request: KyRequest,
options: NormalizedOptions,
response: KyResponse
) => Response | void | Promise<Response | void>;
type BeforeErrorHook = (error: HTTPError) => HTTPError | Promise<HTTPError>;
declare const stop: unique symbol;