curl と Postman でリクエストを送る
毎日使うことになる 2 つのツールと、それぞれの使いどころ。
ここまでは、ブラウザとこのページの「送信」ボタンからリクエストを送ってきました。これで足りるのは単純な GET リクエストだけです。メソッドを選んだり、ヘッダーを設定したり、ボディを送ったりするには、ちゃんとしたクライアントが必要です。 API をテストする人のほとんどは、最終的に 2 つを使い分けます。コマンドラインの curl と、Postman のようなグラフィカルなクライアントです。このレッスンでは、チュートリアルの残りを進めるのに足りる分だけ、それぞれを扱います。
curl
curl はリクエストを送ってレスポンスを表示するコマンドラインのプログラムです。macOS、ほとんどの Linux、Windows 10 と 11 には最初から入っています。curl --version で確かめてください。curl は開発者がリクエストを共有するときの形式でもあります。API のドキュメント、ブラウザの開発者ツール、 Postman はどれもリクエストを curl コマンドとして表示したり書き出したりできるので、ほかのツールが好みでも読めるようになって おく必要があります。
オプションなしだと、curl はボディだけを表示します。-i を付けるとステータス行とレスポンスヘッダーも表示されます。テストではほぼ常にこれが欲しいはずです。
curl -i https://api.testingapis.com/api/healthHTTP/1.1 200 OK
content-type: application/json; charset=utf-8
date: Sun, 11 Oct 2026 11:47:45 GMT
server: Kestrel
x-powered-by: TestingAPIs
transfer-encoding: chunked
{"status":"healthy","uptimeSeconds":76890,"timestamp":"2026-10-11T11:47:46Z"}もっと詳しく見るには -v(詳細表示)を使います。curl が送ったリクエストが > 付きで、レスポンスヘッダーが < 付きで表示されます。* で始まる行は接続についての情報です。リクエストが思いどおりに動かず、通信路を通ったものを正確に見たいときに使いましょう。
curl -v https://api.testingapis.com/api/health* Host api.testingapis.com:443 was resolved.
* IPv4: 135.13.233.203
* Established connection to api.testingapis.com (135.13.233.203 port 443)
* using HTTP/1.x
> GET /api/health HTTP/1.1
> Host: api.testingapis.com
> User-Agent: curl/8.18.0
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< content-type: application/json; charset=utf-8
< date: Sun, 11 Oct 2026 11:49:47 GMT
< transfer-encoding: chunked
...curl は頼んでいないヘッダーを 3 つ付けました。Host、User-Agent、Accept です。どのクライアントも既定のヘッダーをいくつか付け、その中身はクライアントごとに違います。同じリクエストが Postman では動き、curl では失敗するとき、原因は既定のヘッダーであることがよくあります。
メソッド、ヘッダー、ボディ
ほとんどのリクエストは 3 つのオプションでまかなえます。-X はメソッドを設定し、-H はヘッダーを追加し(何度でも使えます)、-d はボディを送ります。次は、受け取ったものを返すエンドポイントへ、JSON のボディ付きで POST を送る例です。
curl -X POST https://api.testingapis.com/api/methods/post \
-H "Content-Type: application/json" \
-d '{"name":"Asha","role":"tester"}'{"method":"POST","message":"POST request received","path":"/api/methods/post","query":{},"contentType":"application/json","bodyLength":31,"bodyTruncated":false,"body":"{\"name\":\"Asha\",\"role\":\"tester\"}","timestamp":"2026-09-30T18:31:16Z"}各行末のバックスラッシュは、bash や zsh でコマンドを次の行へ続けるためのものです。ボディをシングルクォートで囲んでいるのは、 中のダブルクォートにシェルが手を出さないようにするためです。Content-Type ヘッダーを忘れると、curl は application/x-www-form-urlencoded を送ります。-d は HTML フォームのために作られたからで、多くの API はそのボディを拒否します。
curl 7.82 以降には --json という近道があります。ボディを送り、Content-Type: application/json と Accept: application/json を設定し、メソッドを POST に切り替えます。次の例は本物の ToDo を作ります。
curl --json '{"title":"Learn curl","completed":false,"userId":1}' \
https://api.testingapis.com/api/Todos{"message":"Todo created successfully","data":{"id":31,"userId":1,"title":"Learn curl","completed":false,"priority":"medium","dueDate":""}}ほかの人も ToDo を作っているので、返ってくる ID は違うはずです。PUT や PATCH では、--json と一緒に -X PUT や -X PATCH を付けます。
時間の計測とスクリプト
-w は、レスポンスの後に curl が計測した値を表示します。-s(静かに。進捗バーなし)と -o /dev/null(ボディを捨てる)を組み合わせると、1 行の要約が得られます。
curl -s -o /dev/null \
-w "status %{http_code} total %{time_total}s size %{size_download} bytes\n" \
https://api.testingapis.com/api/Productsstatus 200 total 0.382512s size 5846 bytesWindows では -o /dev/null の代わりに -o NUL を使います。time_total には DNS の名前解決、接続、TLS が含まれるので、最初のリクエストはその後のものより遅くなりがちです。パフォーマンスのレッスンで、この数字をさらに分解します。
Windows での curl
同じコマンドがシェルによって 3 通りに振る舞うので、Windows には専用の節が必要です。
Windows PowerShell 5.1(Windows に付属するバージョン)では、curl は curl ではありません。別のオプションを持つ PowerShell のコマンド Invoke-WebRequest のエイリアスなので、curl -i はわかりにくいエラーで失敗します。本物のプログラムを動かすには curl.exe と入力してください。PowerShell 7 ではエイリアスはなくなりましたが、curl.exe はどちらでも動くので、習慣にしておくとよいでしょう。
2 つ目の問題はクォートです。Windows PowerShell 5.1 は、curl.exe のようなプログラムに引数を渡すとき、引数の中のダブルクォートを取り除きます。次のコマンドは正しく見えますが、サーバーには壊れた JSON が届きます。
PS> curl.exe -s -X POST https://api.testingapis.com/api/methods/post -H "Content-Type: application/json" -d '{"name":"Asha"}'
{"method":"POST", ... "bodyLength":11, ... "body":"{name:Asha}", ...}ボディは {name:Asha} として届きましたが、これは JSON ではありません。PowerShell 7.3 以降ではクォートが正しく渡されます。それより古いバージョンでいちばん楽な対処は、ボディをファイルに書き、@ で curl にそのファイルを指定することです。"@body.json" をクォートで囲むのは、PowerShell が @ を独自の構文として扱わないようにするためです。
# body.json contains {"name":"Asha","role":"tester"}
curl.exe -s --json "@body.json" https://api.testingapis.com/api/methods/post昔ながらのコマンドプロンプト(cmd.exe)ではシングルクォートに意味がないので、ボディをダブルクォートで囲み、中のダブルクォート をバックスラッシュでエスケープします。行の継続にはバックスラッシュではなく ^ を使います。
curl -X POST https://api.testingapis.com/api/methods/post ^
-H "Content-Type: application/json" ^
-d "{\"name\":\"Asha\",\"role\":\"tester\"}"Postman とほかの GUI クライアント
GUI クライアントは、コマンドの代わりにフォームを使って curl と同じ仕事をします。ドロップダウンからメソッドを選び、URL を入力し、ヘッダーとボディをタブで埋め、Send をクリックします。レスポンスは下に整形されて、ステータス、時間、サイズと 一緒に表示されます。いちばん広く使われているのは Postman です。Insomnia や Bruno も同じように動き、Bruno はすべてをただのファイルとして保存します。リクエストをコードと同じ Git リポジトリに置けるので、これを好むチームもあります。 以下の考え方はどれにも当てはまります。名前は Postman のものを使います。
コレクション
コレクションは保存されたリクエストのまとまりで、ふつうは API ごとに 1 つ作り、中にフォルダーを置きます。何か月も関わる プロジェクトで curl より GUI クライアントを選ぶ理由はこれです。リクエストを一度組み立てて、コレクションをチームで共有できます。
手で組み立てる必要はありません。この API は、すべてのエンドポイントを機械が読める形で記述した OpenAPI ドキュメントを https://api.testingapis.com/openapi/v1.jsonサインインして表示 で公開しています。Postman で Import を選んでこの URL を貼り付ければ、エンドポイントごとのリクエストを含むコレクションができます。仕事でテストする API のほとんどにも似たファイルがあり、なじみのない API に取りかかるいちばん速い方法です。
環境と変数
実際のプロジェクトでは、同じ API が複数の場所で動いています。開発者のノートパソコン、テストサーバー、ステージング、本番です。 リクエストはベース URL と認証情報を除けば同じです。Postman はこれを環境で扱います。「testingapis」という環境を作り、変数 baseUrl に https://api.testingapis.com を設定して、リクエストの URL を {{baseUrl}}/api/Products/1 と書きます。環境を切り替えれば、すべてのリクエストが一度に切り替わります。トークンも変数に入れておけば、何十ものリクエストに コピーせずに済みます。
Postman でのテスト
各リクエストには Tests タブ(新しいバージョンでは Scripts で、その中の post-response の部分)があり、レスポンスが届いた後に 実行される JavaScript を書けます。GET {{baseUrl}}/api/Products/1 の場合はこうです。
pm.test("status is 200", function () {
pm.response.to.have.status(200);
});
pm.test("product 1 has a price", function () {
const product = pm.response.json();
pm.expect(product.id).to.eql(1);
pm.expect(product.price).to.be.a("number");
});結果はレスポンスの隣の Test Results タブに表示されます。さらに Collection Runner を使えば、コレクションのすべてのリクエストを実行し、どの確認が失敗したかを報告させられます。自動化へのやさしい第一歩です。自動化のレッスンでは、テストをふつうのコードとして書く方法を扱います。数十件を超えると、 こちらの方がうまくスケールします。
どちらを使うか
両方です。仕事によって使い分けます。
| 状況 | 向いているもの |
|---|---|
| 1 つのことを手早く確かめる、またはバグ報告を再現する | curl |
| 正確なリクエストをチケットやチャットで共有する | curl(誰でも貼り付けて実行できる) |
| まだ知らない API を探る | OpenAPI をインポートした GUI クライアント |
| 何度も編集する長い JSON ボディ | GUI クライアント |
| テストサーバーとステージングを切り替える | GUI クライアントの環境 |
| スクリプトの中やビルドサーバーで実行する | curl、またはコードで書いたテスト |
| 生のヘッダーや接続の詳細を見る | curl -v |
この API ならではの選択肢がもう 1 つあります。API リファレンスの各エンドポイントのページには、リクエストを送るフォームと、コピーしてすぐ使える curl コマンドがあります。どこかに保存する前にエンドポイントを試す、いちばん手っ取り早い方法であることがよくあります。
- バグ報告にリクエストを含めるときは、curl コマンドとして添付しましょう。開発者は何もインポートせずに実行でき、どのヘッダーが 送られたかについて疑問の余地がありません。
- Postman は双方向に変換できます。Import ダイアログに curl コマンドを貼り付ければリクエストになり、リクエストの Code ボタンを使えば curl が得られます。
演習
次のことを curl でやってから、GUI クライアントでも繰り返してください。
GET /api/echo/headersを送り、curl が送るヘッダーと GUI クライアントが送るヘッダーを比べてください。 それぞれのツールが自分で付け加えたヘッダーはどれですか。POST /api/Todosで ToDo を作り、レスポンスの ID を後ろに付けたGET /api/Todos/で取得してください。- 同じ POST を
Content-Typeヘッダーなしで送ってください。どんなステータスとボディが返ってきますか。 -wで/api/Productsと/api/Products?delay=2の時間を計ってください。delayパラメーターはサーバーを待たせるので、2 つ目は 2 秒ほど長くかかるはずです。
GUI クライアントで baseUrl 変数を持つ環境を作り、わざと失敗するテストを 1 つ書いてください。成功を当てにする前に、失敗がどう見えるかを知っておくためです。