axios vs ky 徹底比較

axios の詳細ky の詳細
AI生成コンテンツ

この記事はAIによって生成されました。内容の正確性は保証されません。最新の情報は公式ドキュメントをご確認ください。

axios vs ky ― HTTP クライアント徹底比較【2025年版】

1. 結論

ブラウザ・Node.js 両対応で豊富なエコシステムと実績を重視するなら axiosモダンブラウザ向けに軽量かつ Fetch API ベースのシンプルな設計を求めるなら ky を選びましょう。既存の大規模プロジェクトでは axios の安定感が光り、新規のフロントエンド中心プロジェクトでは ky の軽さと洗練された API が魅力です。


2. 比較表

観点axiosky
GitHub Stars≈ 106k≈ 14k
バンドルサイズ (minified+gzip)≈ 13 kB≈ 3.3 kB
ベースとなる APIXMLHttpRequest / http (Node)Fetch API
Node.js サポート✅ ネイティブ対応⚠️ Node 18+ (グローバル fetch 必須)
TypeScript 対応✅ 同梱型定義✅ 同梱型定義
リクエスト/レスポンス インターセプター✅ 組み込みbeforeRequest / afterResponse フック
リトライ機能❌ 別途プラグイン必要✅ 組み込み (retry オプション)
タイムアウトtimeout オプションtimeout オプション (デフォルト 10s)
アップロード進捗onUploadProgress❌ Fetch API の制約で非対応
リクエストキャンセルAbortController / CancelToken (非推奨)AbortController
JSON 自動パース✅ 自動.json() ショートハンド
HTTP エラーのスロー✅ ステータス 2xx 以外で reject✅ ステータス 2xx 以外で HTTPError をスロー
学習コスト低〜中(情報量が豊富)低(API がコンパクト)
週間ダウンロード数 (npm)≈ 60M≈ 4M

3. それぞれの強み

axios の強み

  • 圧倒的な普及率と情報量 Stack Overflow・ブログ記事・書籍での言及数が桁違いに多く、トラブルシューティングが容易です。

  • Node.js でのフルサポート 内部で http / https モジュールを使うため、Node.js のバージョンを問わず安定して動作します。サーバーサイドでの利用実績も豊富です。

  • アップロード/ダウンロード進捗の取得 onUploadProgress / onDownloadProgress コールバックが組み込みで提供されており、ファイルアップロード UI の実装が容易です。

  • インターセプターの柔軟性 リクエスト・レスポンスそれぞれに複数のインターセプターをチェーンでき、認証トークンの付与やエラーハンドリングの一元管理が簡単です。

  • 広範なエコシステム axios-retryaxios-mock-adapteraxios-cache-interceptor など、サードパーティプラグインが充実しています。

ky の強み

  • 圧倒的な軽量さ gzip 後わずか約 3.3 kB。バンドルサイズを厳しく管理するモダン SPA やライブラリ開発に最適です。

  • Fetch API ネイティブ ブラウザ標準の Fetch API をラップしているため、Request / Response / Headers といった Web 標準オブジェクトをそのまま扱えます。

  • 組み込みリトライ ネットワークエラーや 408 / 413 / 429 / 5xx 系エラーに対するリトライが標準搭載されており、追加パッケージが不要です。

  • 洗練されたフック API beforeRequestbeforeRetrybeforeErrorafterResponse の 4 種類のフックが用意されており、宣言的にリクエストライフサイクルを制御できます。

  • .json() ショートハンドメソッド await ky.get(url).json<T>() のように、レスポンスの取得と型付き JSON パースを 1 行で完結できます。


4. コード例で比較

4-1. 基本的な GET リクエスト

axios

import axios from "axios";

interface User {
  id: number;
  name: string;
  email: string;
}

async function fetchUser(id: number): Promise<User> {
  // axios はレスポンスを自動で JSON パースし、data プロパティに格納します
  const { data } = await axios.get<User>(
    `https://jsonplaceholder.typicode.com/users/${id}`
  );
  return data;
}

const user = await fetchUser(1);
console.log(user.name); // "Leanne Graham"

ky

import ky from "ky";

interface User {
  id: number;
  name: string;
  email: string;
}

async function fetchUser(id: number): Promise<User> {
  // ky は .json<T>() で型付きの JSON パースを 1 行で行えます
  return ky
    .get(`https://jsonplaceholder.typicode.com/users/${id}`)
    .json<User>();
}

const user = await fetchUser(1);
console.log(user.name); // "Leanne Graham"

4-2. POST リクエスト(JSON 送信)

axios

import axios from "axios";

interface CreatePostPayload {
  title: string;
  body: string;
  userId: number;
}

interface Post extends CreatePostPayload {
  id: number;
}

async function createPost(payload: CreatePostPayload): Promise<Post> {
  const { data } = await axios.post<Post>(
    "https://jsonplaceholder.typicode.com/posts",
    payload // 第 2 引数にオブジェクトを渡すと自動で JSON シリアライズされます
  );
  return data;
}

const post = await createPost({
  title: "axios で投稿",
  body: "本文です",
  userId: 1,
});
console.log(post.id); // 101

ky

import ky from "ky";

interface CreatePostPayload {
  title: string;
  body: string;
  userId: number;
}

interface Post extends CreatePostPayload {
  id: number;
}

async function createPost(payload: CreatePostPayload): Promise<Post> {
  // json オプションにオブジェクトを渡すと Content-Type も自動設定されます
  return ky
    .post("https://jsonplaceholder.typicode.com/posts", {
      json: payload,
    })
    .json<Post>();
}

const post = await createPost({
  title: "ky で投稿",
  body: "本文です",
  userId: 1,
});
console.log(post.id); // 101

4-3. インターセプター / フックで認証トークンを付与

axios

import axios from "axios";

const api = axios.create({
  baseURL: "https://api.example.com",
  timeout: 5000,
});

// リクエストインターセプター
api.interceptors.request.use((config) => {
  const token = localStorage.getItem("access_token");
  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }
  return config;
});

// レスポンスインターセプター(401 時にリフレッシュする例)
api.interceptors.response.use(
  (response) => response,
  async (error) => {
    if (axios.isAxiosError(error) && error.response?.status === 401) {
      console.error("認証エラー: トークンを更新してください");
      // ここでトークンリフレッシュ処理を実装
    }
    return Promise.reject(error);
  }
);

const { data } = await api.get("/me");
console.log(data);

ky

import ky from "ky";

const api = ky.create({
  prefixUrl: "https://api.example.com",
  timeout: 5000,
  hooks: {
    beforeRequest: [
      (request) => {
        const token = localStorage.getItem("access_token");
        if (token) {
          request.headers.set("Authorization", `Bearer ${token}`);
        }
      },
    ],
    afterResponse: [
      async (_request, _options, response) => {
        if (response.status === 401) {
          console.error("認証エラー: トークンを更新してください");
          // ここでトークンリフレッシュ処理を実装
        }
      },
    ],
  },
});

const data = await api.get("me").json();
console.log(data);

4-4. リトライとタイムアウト

axios(axios-retry を併用)

import axios from "axios";
import axiosRetry from "axios-retry";

const client = axios.create({ timeout: 5000 });

// axios 単体にはリトライ機能がないため、axios-retry を追加します
axiosRetry(client, {
  retries: 3,
  retryDelay: axiosRetry.exponentialDelay, // 指数バックオフ
  retryCondition: (error) =>
    axiosRetry.isNetworkOrIdempotentRequestError(error) ||
    error.response?.status === 429,
});

const { data } = await client.get("https://api.example.com/data");
console.log(data);

ky(組み込みリトライ)

import ky from "ky";

// ky は追加パッケージ不要でリトライを設定できます
const data = await ky
  .get("https://api.example.com/data", {
    timeout: 5000,
    retry: {
      limit: 3,
      methods: ["get"],
      statusCodes: [408, 413, 429, 500, 502, 503, 504],
      backoffLimit: 3000, // バックオフの上限 (ms)
    },
  })
  .json();

console.log(data);

5. どちらを選ぶべきか ― ユースケース別ガイド

ユースケース推奨理由
Node.js サーバーサイド (Express / NestJS など)axiosNode.js 全バージョンで安定動作。ストリーム処理やプロキシ設定も充実
モダンブラウザ向け SPA (React / Vue / Svelte)ky軽量でバンドルサイズを抑えられる。Fetch API ベースで Web 標準に沿った設計
ファイルアップロードで進捗表示が必要axiosonUploadProgress が組み込みで提供されている
ライブラリ / SDK の内部 HTTP クライアントky依存サイズが小さく、利用者のバンドルへの影響を最小化できる
既存の大規模プロジェクトへの導入axios情報量・チームの習熟度・既存コードとの整合性で有利
Cloudflare Workers / Deno / Edge RuntimekyFetch API ベースのため、非 Node.js ランタイムとの相性が良い
リトライ・バックオフを手軽に実装したいky追加パッケージなしで宣言的にリトライを設定可能
レガシーブラウザ (IE11 等) のサポートが必要axiosXMLHttpRequest ベースのため Polyfill なしで動作する

6. まとめ

axios と ky はどちらも優れた HTTP クライアントですが、設計思想が異なります

  • axios は「あらゆる環境で動く万能ナイフ」です。Node.js からレガシーブラウザまで幅広くカバーし、エコシステムの厚さと情報量の多さが最大の武器です。チーム開発や長期運用のプロジェクトでは、この安定感が大きなアドバンテージになります。

  • ky は「Web 標準に寄り添った軽量スカルペル」です。Fetch API をベースにした薄いラッパーでありながら、リトライ・フック・型付き JSON パースといった実用的な機能を備えています。バンドルサイズの制約が厳しいフロントエンドや Edge Runtime 環境では、ky の軽さが際立ちます。

最終的には、プロジェクトの実行環境・チームの技術スタック・バンドルサイズの要件を総合的に判断して選択してください。どちらを選んでも、素の fetch を直接使うよりも生産性の高い HTTP 通信を実現できるはずです。