got の使い方 — Node.js向け高機能HTTPリクエストライブラリ
一言でいうと
got は、Node.js 向けの人間に優しく高機能な HTTP リクエストライブラリです。リトライ、タイムアウト、ストリーム、ページネーション、HTTP/2 など、サーバーサイドで必要になる機能を網羅的に備えています。
どんな時に使う?
- 外部APIとの連携 — REST API やWebhookの呼び出しで、リトライ・タイムアウト・エラーハンドリングをしっかり制御したい場合
- 大量データの取得・ストリーミング — ファイルダウンロードやストリーム処理で、進捗イベントやバックプレッシャー制御が必要な場合
- ページネーション付きAPIの一括取得 — GitHub API のようなカーソルベースのページネーションを自動で処理したい場合
インストール
# npm
npm install got
# yarn
yarn add got
# pnpm
pnpm add got
⚠️ 重要: v12 以降、
gotは ESM (ES Modules) 専用です。CommonJS (require) では使用できません。プロジェクトが CommonJS の場合は ESM への移行が必要です。
基本的な使い方
最もシンプルな GET リクエストと、JSON を送受信する POST リクエストの例です。
import got from 'got';
// GET リクエスト
const response = await got('https://httpbin.org/get');
console.log(response.statusCode); // 200
console.log(response.body); // string
// JSON レスポンスを型付きで取得
interface User {
id: number;
name: string;
email: string;
}
const user = await got.get('https://api.example.com/users/1').json<User>();
console.log(user.name);
// JSON を POST
const created = await got.post('https://api.example.com/users', {
json: {
name: 'Taro Yamada',
email: 'taro@example.com',
},
}).json<User>();
console.log(created.id);
よく使うAPI — got の主要機能と使い方
1. HTTPメソッドショートカット
got.get(), got.post(), got.put(), got.patch(), got.delete() など、各HTTPメソッドに対応したショートカットが用意されています。
import got from 'got';
// GET
const getResponse = await got.get('https://api.example.com/items').json<Item[]>();
// PUT
const updated = await got.put('https://api.example.com/items/1', {
json: { name: 'Updated Item' },
}).json<Item>();
// DELETE
await got.delete('https://api.example.com/items/1');
2. リトライとタイムアウト
デフォルトで失敗時にリトライが有効です(最大2回)。タイムアウトも細かく設定できます。
import got from 'got';
const response = await got('https://api.example.com/data', {
retry: {
limit: 3, // 最大3回リトライ
methods: ['GET', 'POST'], // リトライ対象のメソッド
statusCodes: [408, 429, 500, 502, 503, 504],
backoffLimit: 10_000, // バックオフの上限(ms)
},
timeout: {
request: 10_000, // リクエスト全体のタイムアウト(ms)
lookup: 1_000, // DNS ルックアップのタイムアウト
connect: 3_000, // TCP接続のタイムアウト
response: 5_000, // レスポンス開始までのタイムアウト
},
});
3. ストリームAPI
大きなファイルのダウンロードや、レスポンスをストリームとして処理したい場合に使います。
import got from 'got';
import { createWriteStream } from 'node:fs';
import { pipeline } from 'node:stream/promises';
// ファイルダウンロード
await pipeline(
got.stream('https://example.com/large-file.zip'),
createWriteStream('./large-file.zip'),
);
// 進捗イベントの取得
const stream = got.stream('https://example.com/large-file.zip');
stream.on('downloadProgress', (progress) => {
console.log(`${Math.round(progress.percent * 100)}% complete`);
// transferred: 転送済みバイト数
// total: 全体のバイト数(不明な場合は undefined)
});
await pipeline(stream, createWriteStream('./large-file.zip'));
4. ページネーションAPI
カーソルベースやリンクヘッダーベースのページネーションを自動で処理できます。
import got from 'got';
interface Repo {
name: string;
full_name: string;
}
// GitHub API のリポジトリ一覧を全ページ取得
const repos = await got.paginate.all<Repo>('https://api.github.com/users/sindresorhus/repos', {
pagination: {
paginate({ response }) {
const nextLink = response.headers.link?.match(/<([^>]+)>;\s*rel="next"/);
if (nextLink) {
return { url: new URL(nextLink[1]) };
}
return false; // ページネーション終了
},
transform(response) {
return JSON.parse(response.body) as Repo[];
},
},
headers: {
'user-agent': 'my-app',
},
});
console.log(`Total repos: ${repos.length}`);
// AsyncIterator として逐次処理も可能
for await (const repo of got.paginate<Repo>('https://api.github.com/users/sindresorhus/repos', {
pagination: {
paginate({ response }) {
const nextLink = response.headers.link?.match(/<([^>]+)>;\s*rel="next"/);
return nextLink ? { url: new URL(nextLink[1]) } : false;
},
transform(response) {
return JSON.parse(response.body) as Repo[];
},
},
})) {
console.log(repo.name);
}
5. カスタムインスタンス(Hooks & Defaults)
共通設定をまとめたカスタムインスタンスを作成できます。認証ヘッダーやベースURLの設定に便利です。
import got from 'got';
// カスタムインスタンスの作成
const api = got.extend({
prefixUrl: 'https://api.example.com/v2',
headers: {
'authorization': `Bearer ${process.env.API_TOKEN}`,
'accept': 'application/json',
},
responseType: 'json',
retry: {
limit: 2,
},
hooks: {
beforeRequest: [
(options) => {
console.log(`→ ${options.method} ${options.url?.href}`);
},
],
afterResponse: [
(response) => {
console.log(`← ${response.statusCode} ${response.url}`);
return response;
},
],
beforeError: [
(error) => {
// エラーをカスタマイズ
const { response } = error;
if (response?.body) {
error.message = `${error.message} - ${JSON.stringify(response.body)}`;
}
return error;
},
],
},
});
// prefixUrl が自動付与される(https://api.example.com/v2/users)
const users = await api.get('users').json<User[]>();
// インスタンスのマージも可能
const adminApi = api.extend({
headers: {
'x-admin-key': 'secret',
},
});
類似パッケージとの比較
| 機能 | got | ky | axios | node-fetch | undici (fetch) |
|---|---|---|---|---|---|
| 動作環境 | Node.js のみ | ブラウザ + Node.js | ブラウザ + Node.js | Node.js | Node.js |
| HTTP/2 | ✅ | ✅ | ❌ | ❌ | ❌ |
| ストリームAPI | ✅ | ❌ | ❌ | 部分的 | 部分的 |
| ページネーション | ✅ | ❌ | ❌ | ❌ | ❌ |
| 自動リトライ | ✅ | ✅ | ❌ | ❌ | ❌ |
| RFC準拠キャッシュ | ✅ | ❌ | ❌ | ❌ | ❌ |
| Cookie管理 | ✅ | ❌ | ❌ | ❌ | ❌ |
| 進捗イベント | ✅ | ✅ | ✅ | ❌ | ❌ |
| モジュール形式 | ESM のみ | ESM | CJS + ESM | ESM | CJS + ESM |
| バンドルサイズ | 大きめ | 小さい | 中程度 | 小さい | 組み込み |
公式READMEの推奨: got の作者自身が、ブラウザでも使いたい場合やよりシンプルな用途には Ky(同じ作者)を推奨しています。Ky は Fetch API ベースで軽量です。
注意点・Tips
ESM 必須
v12 以降、CommonJS (require) は使えません。package.json に "type": "module" を設定するか、.mjs 拡張子を使用してください。
{
"type": "module"
}
エラーハンドリングは型を活用する
got は詳細なエラークラスを提供しています。適切にハンドリングしましょう。
import got, { HTTPError, TimeoutError, RequestError } from 'got';
try {
const response = await got('https://api.example.com/data');
} catch (error) {
if (error instanceof HTTPError) {
// 4xx, 5xx レスポンス
console.error(`HTTP ${error.response.statusCode}: ${error.response.body}`);
} else if (error instanceof TimeoutError) {
// タイムアウト
console.error('Request timed out:', error.message);
} else if (error instanceof RequestError) {
// ネットワークエラーなど
console.error('Request failed:', error.message);
}
}
デフォルトのリトライに注意
got はデフォルトで 最大2回リトライ します。POST リクエストなど冪等でない操作では、意図しない重複リクエストが発生する可能性があります。
// 冪等でないリクエストではリトライを無効にする
await got.post('https://api.example.com/orders', {
json: { item: 'widget', quantity: 1 },
retry: { limit: 0 },
});
responseType と .json() の使い分け
// 方法1: オプションで指定(response.body が parsed object になる)
const response = await got<User>('https://api.example.com/users/1', {
responseType: 'json',
});
console.log(response.body.name); // 型推論が効く
// 方法2: .json() チェーン(レスポンスオブジェクトは不要で値だけ欲しい場合)
const user = await got('https://api.example.com/users/1').json<User>();
console.log(user.name);
フォームデータの送信
import got from 'got';
import { FormData, File } from 'formdata-node';
// URL-encoded form
await got.post('https://example.com/login', {
form: {
username: 'taro',
password: 'secret',
},
});
// Multipart form (ファイルアップロード)
const formData = new FormData();
formData.set('file', new File(['hello'], 'hello.txt', { type: 'text/plain' }));
formData.set('description', 'A test file');
await got.post('https://example.com/upload', {
body: formData,
});
HTTP/2 を有効にする
const response = await got('https://api.example.com/data', {
http2: true,
});
まとめ
got は Node.js サーバーサイドにおける HTTP クライアントとして、リトライ・タイムアウト・ストリーム・ページネーション・HTTP/2 など、実運用で必要な機能を一通り備えた成熟したライブラリです。ESM 専用である点と、デフォルトのリトライ挙動には注意が必要ですが、カスタムインスタンスと Hooks を活用すれば、プロジェクト全体で統一された堅牢な HTTP 通信基盤を構築できます。ブラウザ対応が不要な Node.js プロジェクトで、信頼性の高い HTTP クライアントを求めるなら有力な選択肢です。