Got
High-performance HTTP client library for Node.js. Provides rich features equivalent to Axios while achieving superior performance. Supports streaming, advanced error handling, auto-retry, caching, and all APIs including promises, streams, and callbacks.
Library
Got
Overview
Got is "a high-performance HTTP client library for Node.js" that provides rich features comparable to Axios while achieving superior performance. Supporting streams, advanced error handling, automatic retry, caching functionality, and Promise, Stream, and Callback APIs comprehensively. Developed by Sindre Sorhus, it has established a solid position as a high-performance HTTP client in Node.js environments.
Details
Got 2025 edition has established its position as a leading candidate for high-performance HTTP clients in Node.js environments. Particularly gaining adoption in API servers and microservice development where performance is prioritized, it attracts attention with its combination of rich features and high speed. In addition to Promise-based design, it provides native Node.js stream support, advanced retry mechanisms, customizable hook systems, and comprehensive error handling. HTTP/2 support, connection pooling, and automatic redirect processing enable enterprise-level HTTP communication.
Key Features
- High-Performance Architecture: High-speed HTTP communication processing optimized for Node.js
- Streaming Support: Native Node.js stream support
- Advanced Retry Mechanism: Customizable exponential backoff retry
- Comprehensive Error Handling: Detailed error information and context provision
- Hook System: Request/response lifecycle control
- Cache Functionality: Built-in response caching capability
Pros and Cons
Pros
- Higher performance and processing speed than Axios in Node.js environments
- Efficient processing of large-volume data through streaming support
- Robustness through advanced retry mechanisms and error handling
- Improved communication efficiency through HTTP/2 support and connection pooling
- Rich customization options and flexible API design
- Type-safe development through complete TypeScript support
Cons
- Node.js exclusive, unavailable in browser environments
- Higher learning curve than Axios, requiring understanding of advanced features
- Incompatible with browsers, unsuitable for universal applications
- Initial configuration can become complex due to many configuration options
- Ecosystem not as mature as Axios
- Documentation and learning resources more limited than Axios
Reference Pages
Code Examples
Installation and Basic Setup
# Install Got
npm install got
# TypeScript type definitions are automatically included
# @types/got not required
# Recommended for ESM projects
# Special configuration required for CommonJS
Basic Requests (GET/POST/PUT/DELETE)
// ES6 modules import (recommended)
import got from 'got';
// Basic GET request
try {
const { body } = await got('https://api.example.com/users');
console.log('Response:', body);
} catch (error) {
console.error('Error:', error);
}
// JSON response retrieval
const data = await got.get('https://api.example.com/users').json();
console.log('User data:', data);
// TypeScript type specification request
interface User {
id: number;
name: string;
email: string;
}
const users = await got.get('https://api.example.com/users').json<User[]>();
console.log('Type-safe user data:', users);
// POST request (JSON sending)
const newUser = await got.post('https://api.example.com/users', {
json: {
name: 'John Doe',
email: '[email protected]'
}
}).json();
console.log('Created user:', newUser);
// PUT request (update)
const updatedUser = await got.put('https://api.example.com/users/123', {
json: {
name: 'Jane Doe',
email: '[email protected]'
}
}).json();
// DELETE request
await got.delete('https://api.example.com/users/123');
console.log('User deleted');
// Various response format retrieval
const textResponse = await got.get('https://api.example.com/message').text();
const bufferResponse = await got.get('https://api.example.com/binary').buffer();
// Header information retrieval
const response = await got.get('https://api.example.com/info');
console.log('Status:', response.statusCode);
console.log('Headers:', response.headers);
console.log('URL:', response.url);
// Query parameter specification using searchParams
const searchData = await got.get('https://api.example.com/search', {
searchParams: {
q: 'Node.js',
page: 1,
limit: 10
}
}).json();
Advanced Configuration and Customization (Headers, Authentication, Timeout, etc.)
// Custom headers and authentication
const authenticatedData = await got.get('https://api.example.com/private', {
headers: {
'Authorization': 'Bearer your-jwt-token',
'Accept': 'application/json',
'User-Agent': 'MyApp/1.0'
}
}).json();
// Timeout configuration
const dataWithTimeout = await got.get('https://api.example.com/slow', {
timeout: {
request: 5000 // 5 second timeout
}
}).json();
// Detailed timeout configuration
const detailedTimeout = await got.get('https://api.example.com/data', {
timeout: {
lookup: 100, // DNS resolution timeout
connect: 1000, // Connection timeout
secureConnect: 1000, // TLS connection timeout
socket: 2000, // Socket idle timeout
send: 5000, // Send timeout
response: 10000, // Response timeout
request: 30000 // Overall request timeout
}
}).json();
// Client creation using prefix URL
const apiClient = got.extend({
prefixUrl: 'https://api.example.com/v1',
headers: {
'User-Agent': 'MyApp/1.0'
},
timeout: {
request: 10000
}
});
// Requests using base client
const userData = await apiClient.get('users/123').json();
const newPost = await apiClient.post('posts', {
json: { title: 'Title', content: 'Content' }
}).json();
// HTTPS configuration and client certificates
const secureData = await got.get('https://secure-api.example.com/data', {
https: {
rejectUnauthorized: true,
cert: fs.readFileSync('./client.crt'),
key: fs.readFileSync('./client.key'),
ca: fs.readFileSync('./ca.crt')
}
}).json();
// Proxy configuration
const proxyData = await got.get('https://api.example.com/data', {
agent: {
http: new HttpProxyAgent('http://proxy.example.com:8080'),
https: new HttpsProxyAgent('https://proxy.example.com:8080')
}
}).json();
// Cookie configuration
const cookieJar = new CookieJar();
const dataWithCookies = await got.get('https://api.example.com/data', {
cookieJar: cookieJar
}).json();
Error Handling and Retry Functionality
// Comprehensive error handling
try {
const data = await got.get('https://api.example.com/users').json();
} catch (error) {
console.log('Error name:', error.name);
console.log('Error message:', error.message);
if (error.response) {
console.log('Status code:', error.response.statusCode);
console.log('Response body:', error.response.body);
console.log('Request URL:', error.response.url);
console.log('Response headers:', error.response.headers);
}
// Error type-specific processing
if (error.name === 'HTTPError') {
console.log('HTTP error:', error.response.statusCode);
} else if (error.name === 'TimeoutError') {
console.log('Timeout error');
} else if (error.name === 'RequestError') {
console.log('Network error');
} else if (error.name === 'ParseError') {
console.log('Response parse error');
}
}
// Custom retry configuration
const dataWithRetry = await got.get('https://api.example.com/unstable', {
retry: {
limit: 5, // Maximum 5 retries
methods: ['GET', 'POST', 'PUT'], // Retry target methods
statusCodes: [408, 413, 429, 500, 502, 503, 504], // Retry target statuses
errorCodes: ['ETIMEDOUT', 'ECONNRESET', 'ECONNREFUSED'], // Retry target errors
calculateDelay: ({ computedValue }) => computedValue / 2 // Delay time customization
}
}).json();
// Retry information logging with beforeRetry hook
const dataWithRetryLog = await got.get('https://api.example.com/flaky', {
retry: {
limit: 3
},
hooks: {
beforeRetry: [
(error, retryCount) => {
console.log(`Retry [${retryCount}]: ${error.code || error.message}`);
}
]
}
}).json();
// Error customization with beforeError hook
const dataWithCustomError = await got.get('https://api.example.com/data', {
hooks: {
beforeError: [
error => {
const { response } = error;
if (response && response.body) {
error.name = 'CustomAPIError';
error.message = `API Error: ${response.body.message || response.statusCode}`;
}
return error;
}
]
}
}).json();
// Disable retry
const noRetryClient = got.extend({
retry: {
limit: 0
}
});
// Disable throwHttpErrors to get error responses
const response = await got.get('https://api.example.com/maybe-error', {
throwHttpErrors: false
});
if (response.statusCode >= 400) {
console.log('Error response:', response.statusCode);
console.log('Error content:', response.body);
} else {
console.log('Success response:', response.body);
}
Concurrent Processing and Asynchronous Requests
// Parallel execution of multiple requests
async function fetchMultipleEndpoints() {
try {
const [users, posts, comments] = await Promise.all([
got.get('https://api.example.com/users').json(),
got.get('https://api.example.com/posts').json(),
got.get('https://api.example.com/comments').json()
]);
console.log('Users:', users);
console.log('Posts:', posts);
console.log('Comments:', comments);
return { users, posts, comments };
} catch (error) {
console.error('Parallel request error:', error);
throw error;
}
}
// Partial failure tolerance using Promise.allSettled
async function fetchWithPartialFailure() {
const requests = [
got.get('https://api.example.com/reliable').json(),
got.get('https://api.example.com/unreliable').json(),
got.get('https://api.example.com/another').json()
];
const results = await Promise.allSettled(requests);
const successful = results
.filter(result => result.status === 'fulfilled')
.map(result => result.value);
const failed = results
.filter(result => result.status === 'rejected')
.map(result => result.reason);
console.log('Successful:', successful.length);
console.log('Failed:', failed.length);
return { successful, failed };
}
// Pagination-aware data retrieval
async function fetchAllPages(baseUrl) {
const allData = [];
let page = 1;
let hasMore = true;
while (hasMore) {
try {
const pageData = await got.get(baseUrl, {
searchParams: {
page: page,
limit: 20
}
}).json();
allData.push(...pageData.items);
hasMore = pageData.hasMore;
page++;
console.log(`Page ${page - 1} retrieved: ${pageData.items.length} items`);
// API load reduction
if (hasMore) {
await new Promise(resolve => setTimeout(resolve, 100));
}
} catch (error) {
console.error(`Page ${page} error:`, error);
break;
}
}
return allData;
}
// Rate-limited requests
async function rateLimitedRequests(urls, concurrency = 3) {
const results = [];
for (let i = 0; i < urls.length; i += concurrency) {
const batch = urls.slice(i, i + concurrency);
const batchResults = await Promise.allSettled(
batch.map(url => got.get(url).json())
);
results.push(...batchResults);
// Wait between batches
if (i + concurrency < urls.length) {
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
return results;
}
// Duplicate request prevention
const pendingRequests = new Map();
async function deduplicatedRequest(url) {
if (pendingRequests.has(url)) {
return pendingRequests.get(url);
}
const promise = got.get(url).json();
pendingRequests.set(url, promise);
try {
const result = await promise;
return result;
} finally {
pendingRequests.delete(url);
}
}
Framework Integration and Practical Examples
// Express.js proxy server
import express from 'express';
import got from 'got';
const app = express();
app.get('/api/proxy/*', async (req, res) => {
try {
const targetUrl = `https://external-api.example.com${req.path.replace('/api/proxy', '')}`;
const response = await got.get(targetUrl, {
searchParams: req.query,
headers: {
'Authorization': req.headers.authorization
}
});
res.set(response.headers);
res.send(response.body);
} catch (error) {
res.status(error.response?.statusCode || 500);
res.json({ error: error.message });
}
});
// Fastify plugin integration
import fastify from 'fastify';
const server = fastify();
server.register(async function (fastify) {
const apiClient = got.extend({
prefixUrl: 'https://api.example.com',
timeout: { request: 10000 }
});
fastify.decorate('apiClient', apiClient);
});
server.get('/users/:id', async (request, reply) => {
try {
const user = await request.server.apiClient.get(`users/${request.params.id}`).json();
return user;
} catch (error) {
reply.status(error.response?.statusCode || 500);
return { error: error.message };
}
});
// Streaming file upload
import fs from 'node:fs';
import { pipeline } from 'node:stream/promises';
async function uploadFile(filePath, uploadUrl) {
try {
await pipeline(
fs.createReadStream(filePath),
got.stream.post(uploadUrl, {
headers: {
'Content-Type': 'application/octet-stream'
}
})
);
console.log('File upload completed');
} catch (error) {
console.error('Upload error:', error);
throw error;
}
}
// Streaming file download
async function downloadFile(url, outputPath) {
try {
await pipeline(
got.stream(url),
fs.createWriteStream(outputPath)
);
console.log('File download completed');
} catch (error) {
console.error('Download error:', error);
throw error;
}
}
// Authentication token auto-refresh functionality
class AuthenticatedClient {
constructor(baseUrl, credentials) {
this.baseUrl = baseUrl;
this.credentials = credentials;
this.token = null;
this.tokenExpiry = null;
this.client = got.extend({
prefixUrl: baseUrl,
hooks: {
beforeRequest: [
async (options) => {
await this.ensureValidToken();
options.headers.authorization = `Bearer ${this.token}`;
}
],
afterResponse: [
(response, retryWithMergedOptions) => {
if (response.statusCode === 401) {
this.token = null; // Reset token
return retryWithMergedOptions();
}
return response;
}
]
}
});
}
async ensureValidToken() {
if (this.token && this.tokenExpiry && Date.now() < this.tokenExpiry) {
return; // Valid token exists
}
await this.refreshToken();
}
async refreshToken() {
const response = await got.post(`${this.baseUrl}/auth/token`, {
json: this.credentials
}).json();
this.token = response.access_token;
this.tokenExpiry = Date.now() + (response.expires_in * 1000);
}
async get(url, options = {}) {
return this.client.get(url, options);
}
async post(url, options = {}) {
return this.client.post(url, options);
}
}
// Usage example
const authClient = new AuthenticatedClient('https://api.example.com', {
username: 'user',
password: 'pass'
});
const userData = await authClient.get('users/me').json();
const newPost = await authClient.post('posts', {
json: { title: 'Title' }
}).json();