Universal WHATWG Fetch API for Node, Browsers, Workers and React Native. Cross-fetch provides platform-agnostic HTTP request functionality that works seamlessly across different JavaScript runtime environments while adhering to the WHATWG fetch specification for consistent behavior.
npm install cross-fetchimport fetch from 'cross-fetch';For named imports:
import { fetch, Request, Response, Headers } from 'cross-fetch';CommonJS:
const fetch = require('cross-fetch');
// or
const { fetch, Request, Response, Headers } = require('cross-fetch');import 'cross-fetch/polyfill';
// Now fetch is available globally as window.fetch (browser) or global.fetch (Node.js)CommonJS:
require('cross-fetch/polyfill');
// Now fetch is available globally as window.fetch (browser) or global.fetch (Node.js)<script src="//unpkg.com/cross-fetch/dist/cross-fetch.js"></script>
<!-- Now fetch is available as window.fetch -->import fetch from 'cross-fetch';
const response = await fetch('https://api.example.com/data');
if (response.status >= 400) {
throw new Error('Bad response from server');
}
const data = await response.json();
console.log(data);import fetch from 'cross-fetch';
const response = await fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'John Doe',
email: 'john@example.com'
})
});
const result = await response.json();import { fetch, Request, Response, Headers } from 'cross-fetch';
const headers = new Headers({
'Authorization': 'Bearer token123',
'Content-Type': 'application/json'
});
const request = new Request('https://api.example.com/protected', {
method: 'GET',
headers: headers
});
const response = await fetch(request);
const data = await response.text();The main HTTP request function that provides universal fetch API across all platforms.
/**
* Performs HTTP requests following the WHATWG Fetch API specification
* @param input - URL string or Request object
* @param init - Optional request configuration
* @returns Promise that resolves to a Response object
*/
declare function fetch(input: RequestInfo, init?: RequestInit): Promise<Response>;
// Type definitions for input and options
type RequestInfo = Request | string;
interface RequestInit {
method?: string;
headers?: HeadersInit;
body?: BodyInit | null;
referrer?: string;
referrerPolicy?: ReferrerPolicy;
mode?: RequestMode;
credentials?: RequestCredentials;
cache?: RequestCache;
redirect?: RequestRedirect;
integrity?: string;
keepalive?: boolean;
signal?: AbortSignal | null;
}Platform-specific behavior:
node-fetch internally, auto-prefixes schemaless URIs (//api.com → https://api.com)Special properties:
fetch.ponyfill === true when used as ponyfillfetch.polyfill === true when used as polyfillCreates Request objects following the WHATWG Request API specification.
/**
* Request constructor for creating HTTP request objects
* @param input - URL string or existing Request object
* @param init - Optional request configuration
*/
declare class Request {
constructor(input: RequestInfo, init?: RequestInit);
readonly method: string;
readonly url: string;
readonly headers: Headers;
readonly destination: RequestDestination;
readonly referrer: string;
readonly referrerPolicy: ReferrerPolicy;
readonly mode: RequestMode;
readonly credentials: RequestCredentials;
readonly cache: RequestCache;
readonly redirect: RequestRedirect;
readonly integrity: string;
readonly keepalive: boolean;
readonly signal: AbortSignal;
clone(): Request;
arrayBuffer(): Promise<ArrayBuffer>;
blob(): Promise<Blob>;
formData(): Promise<FormData>;
json(): Promise<any>;
text(): Promise<string>;
}Creates Response objects following the WHATWG Response API specification.
/**
* Response constructor for creating HTTP response objects
* @param body - Optional response body
* @param init - Optional response configuration
*/
declare class Response {
constructor(body?: BodyInit | null, init?: ResponseInit);
readonly type: ResponseType;
readonly url: string;
readonly redirected: boolean;
readonly status: number;
readonly ok: boolean;
readonly statusText: string;
readonly headers: Headers;
readonly body: ReadableStream<Uint8Array> | null;
readonly bodyUsed: boolean;
static error(): Response;
static redirect(url: string, status?: number): Response;
clone(): Response;
arrayBuffer(): Promise<ArrayBuffer>;
blob(): Promise<Blob>;
formData(): Promise<FormData>;
json(): Promise<any>;
text(): Promise<string>;
}
interface ResponseInit {
status?: number;
statusText?: string;
headers?: HeadersInit;
}Creates Headers objects following the WHATWG Headers API specification.
/**
* Headers constructor for managing HTTP headers
* @param init - Optional initial headers
*/
declare class Headers {
constructor(init?: HeadersInit);
append(name: string, value: string): void;
delete(name: string): void;
get(name: string): string | null;
has(name: string): boolean;
set(name: string, value: string): void;
forEach(callbackfn: (value: string, key: string, parent: Headers) => void, thisArg?: any): void;
entries(): IterableIterator<[string, string]>;
keys(): IterableIterator<string>;
values(): IterableIterator<string>;
[Symbol.iterator](): IterableIterator<[string, string]>;
}
type HeadersInit = Headers | Record<string, string> | [string, string][];Supports request cancellation using the AbortController API for timeout and manual cancellation.
/**
* AbortController integration for request cancellation
* Use the signal property in RequestInit to enable cancellation
*/
interface AbortController {
readonly signal: AbortSignal;
abort(): void;
}
interface AbortSignal {
readonly aborted: boolean;
addEventListener(type: 'abort', listener: () => void): void;
removeEventListener(type: 'abort', listener: () => void): void;
}// Body types that can be sent in requests or responses
type BodyInit = ArrayBuffer | ArrayBufferView | Blob | FormData | ReadableStream<Uint8Array> | URLSearchParams | string;
// Request modes
type RequestMode = "cors" | "no-cors" | "same-origin" | "navigate";
// Credential handling
type RequestCredentials = "omit" | "same-origin" | "include";
// Cache modes
type RequestCache = "default" | "no-store" | "reload" | "no-cache" | "force-cache" | "only-if-cached";
// Redirect handling
type RequestRedirect = "follow" | "error" | "manual";
// Response types
type ResponseType = "basic" | "cors" | "default" | "error" | "opaque" | "opaqueredirect";
// Referrer policies
type ReferrerPolicy = "" | "no-referrer" | "no-referrer-when-downgrade" | "same-origin" | "origin" | "strict-origin" | "origin-when-cross-origin" | "strict-origin-when-cross-origin" | "unsafe-url";
// Request destinations
type RequestDestination = "" | "audio" | "audioworklet" | "document" | "embed" | "font" | "frame" | "iframe" | "image" | "manifest" | "object" | "paintworklet" | "report" | "script" | "serviceworker" | "sharedworker" | "style" | "track" | "video" | "worker" | "xslt";Cross-fetch automatically detects the runtime environment and uses the appropriate implementation:
node-fetch package with additional schemaless URI support (//example.com → https://example.com)fetch or falls back to whatwg-fetch polyfillfetch APIThe package provides different builds for different environments:
dist/node-ponyfill.js - Node.js ponyfill using node-fetchdist/browser-ponyfill.js - Browser ponyfill with whatwg-fetch fallbackdist/react-native-ponyfill.js - React Native using global fetchThe appropriate bundle is automatically selected based on your environment and module system, with specific support for:
require())import)Ponyfill (Recommended): Import locally without modifying global scope. Safer for libraries and applications as it avoids potential conflicts.
import fetch from 'cross-fetch';
// Use fetch function directly - isolated to your module
const response = await fetch('https://api.example.com');Polyfill: Installs globally by modifying the global object. Use when you want drop-in replacement for native fetch.
import 'cross-fetch/polyfill';
// Now window.fetch (browser) or global.fetch (Node.js) is available everywhere
const response = await fetch('https://api.example.com'); // Using global fetchKey differences:
fetch.ponyfill === true, no global pollution, explicit importsfetch.polyfill === true, global installation, implicit availabilityimport fetch from 'cross-fetch';
try {
const response = await fetch('https://api.example.com/data');
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
// Process data
} catch (error) {
console.error('Fetch failed:', error);
}import fetch from 'cross-fetch';
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 5000);
try {
const response = await fetch('https://api.example.com/data', {
signal: controller.signal
});
clearTimeout(timeoutId);
const data = await response.json();
// Process data
} catch (error) {
if (error.name === 'AbortError') {
console.log('Request was aborted');
} else {
console.error('Fetch failed:', error);
}
}