curl はHTTPの「何でも屋」。ブラウザやGUIツールを開かなくても、コマンド1行でAPIの応答・ステータス・ヘッダ・TLSの中身まで確認できます。この記事は「やりたいこと→コマンド→注意点」のユースケース逆引きで、疎通確認・認証・ヘルスチェック・CDN確認の実務断片をまとめました。最後に1画面で引ける逆引き早見表も付けています。
01なぜcurlか — HTTPの「何でも屋」
curl(カール)は、HTTPリクエストをコマンド1本で送れるツールです。ブラウザやPostmanのようなGUIを開かなくても、API・Webサーバ・ロードバランサが返す「生の応答」をその場で確認できます。
「つながらない」「500が返る」「なぜか遅い」——こうしたときの疎通確認の第一手がcurlです。名前解決(DNS)・TCP接続・TLSハンドシェイク・HTTPステータスのどこで詰まっているのかを、1コマンドずつ切り分けられます。
- ほぼ全てのLinux/macに標準搭載。最近のWindowsにも入っており、SSHで入った先でもすぐ使える。
- ヘッダ・ステータス・本文・TLS情報まで、見たいものだけを取り出せる。
- スクリプトやCI、デプロイ後のヘルスチェックにそのまま組み込める。
curl -I URL でステータスとヘッダだけ見るのが定番です。本文をダラダラ流さずに「生きているか」を確認できます。02基本オプション — まずこれだけ
最初に覚えるのはこの7つで十分です。組み合わせるだけで大半の確認ができます。
# ヘッダ+本文を表示(-i)
curl -i https://api.example.com/health
# ヘッダだけ=HEAD(-I)。生死とリダイレクト先の確認に
curl -I https://example.com/
# 詳細(-v):接続・TLS・送受信ヘッダまで全部見える
curl -v https://api.example.com/health
# 静かに本文だけ(-s は進捗バーを消す)
curl -s https://api.example.com/health
# 保存:-o は指定名で、-O はURL末尾のファイル名で保存
curl -s -o result.json https://api.example.com/data
curl -O https://example.com/archive.tar.gz
# リダイレクト(3xx)を自動で追う(-L)
curl -L https://example.com/ -s(進捗を消す)と -S(エラーは出す)をセットに。curl -sS URL なら、普段は静かでエラー時だけ理由が出ます。03ユースケース:APIを叩く
REST APIの疎通確認は、メソッド(-X)・ヘッダ(-H)・ボディ(-d)の3点セットで組み立てます。
# POST(JSONボディ)
curl -X POST https://api.example.com/v1/items \
-H 'Content-Type: application/json' \
-d '{"name":"widget","qty":3}'
# 大きい/厳密なボディはファイルから(改行や空白をそのまま送る)
curl -X POST https://api.example.com/v1/items \
-H 'Content-Type: application/json' \
--data-binary @body.json
# GET(クエリ付き。&を含むのでURL全体をクォートで囲う)
curl -s 'https://api.example.com/v1/items?limit=10&sort=desc'
# PUT / DELETE
curl -X PUT https://api.example.com/v1/items/42 \
-H 'Content-Type: application/json' -d '{"qty":5}'
curl -X DELETE https://api.example.com/v1/items/42 -d(--data)は改行を除去してから送ります(フォーム的な挙動)。JSONの改行・空白を厳密に保ちたいときは --data-binary @file を使ってください。curl -s URL | jq '.items[].id' のように繋げます。jq側は jq 実践リファレンス にまとめています。04ユースケース:認証を付ける
多くのAPIはトークンやBasic認証を要求します。認証情報はヘッダ(-H)かユーザ指定(-u)で渡します。
# Bearer トークン(一番よく使う)
curl -H 'Authorization: Bearer YOUR_TOKEN' https://api.example.com/v1/me
# トークンは環境変数に置いてコマンド履歴に残さない
export TOKEN="YOUR_TOKEN"
curl -H "Authorization: Bearer $TOKEN" https://api.example.com/v1/me
# Basic 認証(user:pass)。パスワードを省略すると対話入力にできる
curl -u alice:YOUR_PASSWORD https://api.example.com/private
curl -u alice https://api.example.com/private
# APIキーを独自ヘッダで
curl -H 'X-API-Key: YOUR_KEY' https://api.example.com/v1/data AWSのAPIを直接叩きたい場合、curlには --aws-sigv4 によるSigV4署名オプションがあります。ただしリージョン・サービス名・認証情報の指定が細かく、鍵の取り回しも自前になります。AWS APIを叩くなら、署名と一時認証情報の更新を自動でやってくれる AWS CLI を推奨します。curlのSigV4は「CLIが入れられない最小環境での確認」など限定用途に留めるのが安全です。
YOUR_TOKEN などは、必ず自分の値に置き換えるプレースホルダです。05ユースケース:疎通とデバッグ
「どこで詰まっているか」を切り分けるのがcurlの真骨頂です。ステータス・所要時間・DNS・TLSを一つずつ確認します。
# ステータスと所要時間だけ知りたい(本文は捨てる)
curl -w '%{http_code} %{time_total}\n' -o /dev/null -s https://example.com/
# DNSを上書きして特定サーバに直接当てる(LB配下の1台を検証)
curl --resolve api.example.com:443:10.0.1.23 https://api.example.com/health
# タイムアウトを付けてハングを防ぐ
curl --connect-timeout 3 --max-time 10 https://api.example.com/health
# TLSの中身(証明書・プロトコル)を確認
curl -v https://example.com/ 2>&1 | grep -Ei 'SSL|TLS|subject|issuer|expire' -w で使える主な変数:%{http_code}(ステータス)/%{time_namelookup}(名前解決まで)/%{time_connect}(TCP接続まで)/%{time_appconnect}(TLSまで)/%{time_total}(合計)。段階ごとの秒数を並べると「DNSが遅い」「TLSが遅い」の切り分けができます。--resolve host:port:IP は /etc/hosts を汚さずにDNSだけ差し替えられます。ALBの背後にある特定AZ・特定インスタンスを名指しで確認したいときに便利です。06ユースケース:運用(ヘルスチェック・メタデータ)
AWS運用では、ロードバランサや監視スクリプトからの疎通確認にcurlが活躍します。
ヘルスチェックの確認:ALB経由の応答と、ターゲット(EC2)を直接叩いた応答を見比べると、問題がLBとアプリのどちらにあるか切り分けられます。
# ターゲット(アプリ)を直接叩いて 200 を返すか確認
curl -i http://10.0.2.15:8080/healthz
# ALB経由の応答(ステータス行だけ)
curl -sI https://app.example.com/ | head -n 1 IMDSv2でメタデータ取得:EC2ではトークン必須の IMDSv2 が既定・推奨です。まず PUT でトークンを取得し、次にそのトークンをヘッダに付けて GET する2段階が現行の正しい手順です。
# 1) PUTでトークンを取得(TTL付き、最大21600秒)
TOKEN=$(curl -sX PUT "http://169.254.169.254/latest/api/token" \
-H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
# 2) トークンをヘッダに付けてGET
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" \
http://169.254.169.254/latest/meta-data/instance-id PUT でトークンを取ってから X-aws-ec2-metadata-token ヘッダ付きの GET、という順を守ってください。スクリプトでの失敗検知:監視やデプロイ後チェックでは、HTTPエラーを終了コードに反映させます。
# 4xx/5xx を「失敗」として終了コードに反映(-f)
if curl -fsS https://api.example.com/health > /dev/null; then
echo "healthy"
else
echo "unhealthy (exit=$?)"; exit 1
fi -f(失敗時は終了コード22で落ちる)+ -sS が基本形です。-f を付けないと 500 でも終了コード0で「成功」扱いになり、障害を見逃します。シェル側の書き方は Linux実践コマンド逆引き も参考にどうぞ。07ユースケース:CDN・キャッシュ確認
CDNが効いているか、キャッシュがHIT/MISSのどちらかは、レスポンスヘッダを見れば分かります。本体をダウンロードせずHEADで確認するのがコツです。
# キャッシュ関連ヘッダだけ抜き出す
curl -sI https://cdn.example.com/assets/app.js | grep -iE 'cache|age|etag|x-cache|cf-'
# 部分取得(Range):先頭1KBだけ取得して確認
curl -r 0-1023 -o head.bin https://cdn.example.com/large.bin X-Cache(Hit from cloudfront / Miss from cloudfront)と Age、Cloudflareは CF-Cache-Status(HIT/MISS/EXPIRED)。加えて多くのCDNで Cache-Control・ETag・Age が効きます。ヒット率が上がらないときは、まずこれらのヘッダを突き合わせます。CDNごとの違いは CDN比較(CloudFront/Cloudflare/Akamai) にまとめています。-I(HEAD)ならオブジェクト本体を落とさずにヘッダだけ確認できます。大きなアセットのキャッシュ状態確認はHEADで十分なことが多いです。08つまずきポイント
-dを付けると自動でPOSTになり、Content-Type: application/x-www-form-urlencodedが既定で付く。JSONを送るなら-H 'Content-Type: application/json'を明示する。-d @file/--data-binary @fileの@は「ファイルの中身を読む」という意味。@を付け忘れると、文字列 body.json がそのまま送られてしまう。-dは改行を落とす。改行込みで送りたいなら--data-binary @fileを使う。-k(--insecure)はTLS証明書の検証を無効化する。原因を隠すだけなので本番スクリプトには残さない。証明書エラーは基本「直す」もの。
スペースや記号を含むクエリは、自前で組み立てず --data-urlencode にエンコードさせます。
# フォーム値を安全にURLエンコードして送る
curl -G https://api.example.com/search \
--data-urlencode 'q=hello world & more' \
--data-urlencode 'lang=ja'
# -G を付けると --data-* をボディではなくクエリ文字列に回す(GETになる) -d の自動POST化と Content-Type の既定は「ハマりの二大巨頭」です。JSON APIでは -X POST(または -d に任せる)+ -H 'Content-Type: application/json' をセットで書く癖をつけると事故りません。09逆引き早見表(1画面チートシート)
「やりたいこと」から引けるようにまとめました。ブックマークして、そのままコピペで使えます。
| やりたいこと | curlコマンド |
|---|---|
| ステータス+ヘッダを見る | curl -i URL |
| ヘッダだけ(HEAD) | curl -I URL |
| 詳細(TLS・接続)を見る | curl -v URL |
| 静かに本文だけ取得 | curl -s URL |
| ファイルに保存 | curl -o out.json URL / curl -O URL |
| リダイレクトを追う | curl -L URL |
| JSONをPOST | curl -X POST -H 'Content-Type: application/json' -d '{...}' URL |
| Bearer認証を付ける | curl -H 'Authorization: Bearer YOUR_TOKEN' URL |
| ステータス+所要時間だけ | curl -w '%{http_code} %{time_total}\n' -o /dev/null -s URL |
| DNSを上書きして当てる | curl --resolve host:443:IP https://host/ |
| タイムアウトを付ける | curl --connect-timeout 3 --max-time 10 URL |
| 失敗を終了コードに反映 | curl -fsS URL |
| キャッシュ状態を確認 | curl -sI URL | grep -i x-cache |
| IMDSv2でメタデータ取得 | PUTでトークン取得 → X-aws-ec2-metadata-token 付きGET |
10よくある質問(FAQ)
curlとwget、どちらを使えばいい?
単発のAPI疎通・ヘッダ確認・デバッグは curl が得意です(HTTPメソッド指定やヘッダ操作が柔軟)。大きなファイルのダウンロードやサイトのミラーリングは wget が向きます。運用の切り分けでは、まず curl を1つ手に馴染ませておくと応用が利きます。
-k を使わないと証明書エラーで確認できません。
-k(検証無効化)は原因を隠すだけで、本番運用では危険です。多くは中間CA証明書の不足・時刻ずれ・SNI不一致が原因です。まず curl -v でどの証明書のどこで失敗しているかを確認し、--cacert で正しいCAを指定するか、サーバ側の証明書チェーン設定を直すのが本筋です。
JSONをPOSTしているのにサーバが受け取れません。
-d だけだと Content-Type がフォーム扱い(application/x-www-form-urlencoded)になります。-H 'Content-Type: application/json' を必ず付けてください。改行や構造を厳密に保ちたい場合は --data-binary @body.json を使うと安全です。
シェルスクリプトの監視でHTTPエラーを検知したい。
-f(--fail)を付けると 4xx/5xx で終了コードが非0(22)になり、if 文やCIで失敗として扱えます。進捗を消しつつエラーは表示する -sS と合わせて curl -fsS URL が定番です。-f なしだと 500 でも終了コード0になり見逃します。
curlのような基礎ツールを「なぜ・いつ使うか」まで含めて身につけたい方へ。EMWは札幌からAWSの設計・運用・移行を支援しています。基礎から積み上げたいエンジニアのカジュアル面談も歓迎です。
相談する