Overview Install Files SecuritySummary Cloudflare Workers Runtime APIs including Fetch, Streams, Crypto, Cache, WebSockets, and Encoding. Use for HTTP requests, streaming, encryption, caching, real-time connections, or encountering API compatibility, response handling, stream processing errors.
Cloudflare Workers Runtime APIs
Master the Workers runtime APIs: Fetch, Streams, Crypto, Cache, WebSockets, and text encoding.
Quick Reference
API Purpose Common Use Fetch HTTP requests External APIs, proxying Streams Data streaming Large files, real-time Crypto Cryptography Hashing, signing, encryption Cache Response caching Performance optimization WebSockets Real-time connections Chat, live updates Encoding Text encoding UTF-8, Base64
Quick Start: Fetch API
export default {
async fetch(request: Request, env: Env): Promise<Response> {
// Basic fetch
const response = await fetch('https://api.example.com/data');
// With options
const postResponse = await fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${env.API_KEY}`,
},
body: JSON.stringify({ name: 'John' }),
});
// Clone for multiple reads
const clone = response.clone();
const json = await response.json();
const text = await clone.text();
return Response.json(json);
}
};
Critical Rules
Always set timeouts for external requests - Workers have a 30s limit, external APIs can hang
Clone responses before reading body - Body can only be read once
Use streaming for large payloads - Don't buffer entire response in memory
Cache external API responses - Reduce latency and API costs
Handle Crypto operations in try/catch - Invalid inputs throw errors
WebSocket hibernation for cost - Use Durable Objects with hibernation
Top 10 Errors Prevented Error Symptom Prevention Body already read TypeError: Body has already been consumedClone response before reading Fetch timeout Request hangs, worker times out Use AbortController with timeout Invalid JSON SyntaxError: Unexpected tokenCheck content-type before parsing Stream locked TypeError: ReadableStream is lockedDon't read stream multiple times Crypto key error DOMException: Invalid keyDataValidate key format and algorithm Cache miss Returns undefined instead of response Check cache before returning WebSocket close Connection drops unexpectedly Handle close event, implement reconnect Encoding error TypeError: Invalid code pointUse TextEncoder/TextDecoder properly CORS blocked Browser rejects response Add proper CORS headers Request size 413 Request Entity Too LargeStream large uploads
Fetch API Patterns
With Timeout async function fetchWithTimeout(url: string, timeout: number = 5000): Promise<Response> {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
try {
const response = await fetch(url, { signal: controller.signal });
return response;
} finally {
clearTimeout(timeoutId);
}
}
With Retry async function fetchWithRetry(
url: string,
options: RequestInit = {},
retries: number = 3
): Promise<Response> {
for (let i = 0; i < retries; i++) {
try {
const response = await fetch(url, options);
if (response.ok) return response;
// Retry on 5xx errors
if (response.status >= 500 && i < retries - 1) {
await new Promise(r => setTimeout(r, Math.pow(2, i) * 1000));
continue;
}
return response;
} catch (error) {
if (i === retries - 1) throw error;
await new Promise(r => setTimeout(r, Math.pow(2, i) * 1000));
}
}
throw new Error('Max retries exceeded');
}
Streams API
Transform Stream function createUppercaseStream(): TransformStream<string, string> {
return new TransformStream({
transform(chunk, controller) {
controller.enqueue(chunk.toUpperCase());
}
});
}
// Usage
const response = await fetch('https://example.com/text');
const transformed = response.body!
.pipeThrough(new TextDecoderStream())
.pipeThrough(createUppercaseStream())
.pipeThrough(new TextEncoderStream());
return new Response(transformed);
Stream Large Response async function streamLargeFile(url: string): Promise<Response> {
const response = await fetch(url);
// Stream directly without buffering
return new Response(response.body, {
headers: {
'Content-Type': response.headers.get('Content-Type') || 'application/octet-stream',
},
});
}
Crypto API
Hashing async function sha256(data: string): Promise<string> {
const encoder = new TextEncoder();
const dataBuffer = encoder.encode(data);
const hashBuffer = await crypto.subtle.digest('SHA-256', dataBuffer);
const hashArray = Array.from(new Uint8Array(hashBuffer));
return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
}
HMAC Signing async function signHMAC(key: string, data: string): Promise<string> {
const encoder = new TextEncoder();
const keyData = encoder.encode(key);
const dataBuffer = encoder.encode(data);
const cryptoKey = await crypto.subtle.importKey(
'raw',
keyData,
{ name: 'HMAC', hash: 'SHA-256' },
false,
['sign']
);
const signature = await crypto.subtle.sign('HMAC', cryptoKey, dataBuffer);
return btoa(String.fromCharCode(...new Uint8Array(signature)));
}
Cache API export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
const cache = caches.default;
const cacheKey = new Request(request.url, { method: 'GET' });
// Check cache
let response = await cache.match(cacheKey);
if (response) {
return response;
}
// Fetch and cache
response = await fetch(request);
response = new Response(response.body, response);
response.headers.set('Cache-Control', 'public, max-age=3600');
// Store in cache (don't await)
ctx.waitUntil(cache.put(cacheKey, response.clone()));
return response;
}
};
WebSockets (Durable Objects) // Durable Object with WebSocket hibernation
export class WebSocketRoom {
state: DurableObjectState;
constructor(state: DurableObjectState) {
this.state = state;
}
async fetch(request: Request): Promise<Response> {
const upgradeHeader = request.headers.get('Upgrade');
if (upgradeHeader !== 'websocket') {
return new Response('Expected websocket', { status: 426 });
}
const pair = new WebSocketPair();
const [client, server] = Object.values(pair);
// Accept with hibernation
this.state.acceptWebSocket(server);
return new Response(null, { status: 101, webSocket: client });
}
async webSocketMessage(ws: WebSocket, message: string | ArrayBuffer) {
// Handle incoming message
const data = typeof message === 'string' ? message : new TextDecoder().decode(message);
// Broadcast to all connected clients
for (const client of this.state.getWebSockets()) {
client.send(data);
}
}
async webSocketClose(ws: WebSocket, code: number, reason: string) {
ws.close(code, reason);
}
}
When to Load References Load specific references based on the task:
Making HTTP requests? → Load references/fetch-api.md for timeout, retry, proxy patterns
Processing large data? → Load references/streams-api.md for TransformStream, chunking
Encryption/signing? → Load references/crypto-api.md for AES, RSA, JWT verification
Caching responses? → Load references/cache-api.md for Cache API patterns, TTL strategies
Real-time features? → Load references/websockets.md for WebSocket patterns, Durable Objects
Text encoding? → Load references/encoding-api.md for TextEncoder, Base64, Unicode
Templates Template Purpose Use When templates/fetch-patterns.tsHTTP request utilities Building API clients templates/stream-processing.tsStream transformation Processing large files templates/crypto-operations.tsCrypto utilities Signing, hashing, encryption templates/websocket-handler.tsWebSocket DO Real-time applications
Resources