結論

curl(カール)は、URLを指定してサーバーとデータをやり取りするコマンドです。curl URL の1行で、返ってきた中身が画面に出ます。

この記事でわかること

  • 目的別の早見表と、よく使うオプション約70個
  • -v の読み方と、API 確認8パターンの実行結果
  • 終了コード全87個の原文と、エラー16例の直し方

2026年10月24日更新|curl 8.23.0・8.5.0(Ubuntu 24.04)で実行確認

curl は、オプションで「送るリクエスト」を組み立て、サーバーから返ってきた「レスポンス」を画面かファイルに出します。

flowchart TD
    A[curl URL を実行] --> B[リクエストを送る<br>メソッド・ヘッダー・本文]
    B --> C[サーバー]
    C --> D[レスポンスが返る<br>ステータス・ヘッダー・本文]
    D --> E[画面に表示<br>何も付けないとき]
    D --> F[ファイルに保存<br>-o・-O]

よく調べられる使い方を先にまとめます。どれも、この記事のために立てた手元のサーバーに向けて実行し、結果を本文に載せています。

やりたいこと コマンド 詳しい節
ページや API の中身を見る curl URL curlとは
レスポンスヘッダーも見る curl -i URL -v の読み方
やり取りを全部見る curl -v URL -v の読み方
JSON を POST する curl --json '{"a":1}' URL API の確認
ファイルとして保存する curl -LO URL ダウンロード
トークンを付ける curl -H 'Authorization: Bearer X' URL API の確認
ステータスコードだけ出す curl -s -o /dev/null -w '%{http_code}\n' URL -w
Windows PowerShell 5.1 で使う curl.exe URL(.exe まで書く) Windows
4xx・5xx を失敗にする curl -sS --fail-with-body URL スクリプト

確認環境:Ubuntu 24.04.4 LTS で、curl 8.23.0(2026-10-14 リリース。curl 公式のソースを OpenSSL 3.0.13・nghttp2 1.59.0 でビルド)と、Ubuntu 24.04 の apt の curl 8.5.0 を実行しました。相手は 127.0.0.1 で動かした Python 3.11.15 のテスト用 HTTP サーバーと、自作の認証局で証明書を発行した nginx 1.24.0(HTTPS・HTTP/2)です。比較に GNU Wget 1.21.4、wcurl 2026.10.12(curl 8.23.0 に同梱)、PowerShell 7.6.4(Linux 版)、jq 1.7 を使いました。Windows 同梱の curl・Windows PowerShell 5.1・HTTP/3・Chrome の開発者ツールは、curl 公式・Microsoft・Chrome の公式ドキュメントで確かめています(確認日 2026年10月24日)。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「curlとは?curlコマンドの使い方とオプション一覧|Windows・エラー対処」

curlとは:URLでデータを送受信するコマンド

この節では、curl が何をする道具で、最初の1行を打つと何が起きるのかが分かります。

curl は、URL を使ってサーバーとデータを送ったり受け取ったりするコマンドラインツールです。 curl のマニュアルは「curl is a tool for transferring data from or to a server using URLs.」と説明しています。ブラウザが画面に描く前の「生のやり取り」を、文字のまま見たり組み立てたりできます。

  • 読み方:「カール」。curl の FAQ には、k の音で始め、girl・earl と同じ韻で読むと書かれています
  • 名前の由来:「Client for URLs(URL のためのクライアント)」をもじった名前で、「see URL(URL を見る)」とも読めることも名前に合っていた、と FAQ にあります
  • 中身:転送の機能は libcurl というライブラリにあり、curl コマンドはその窓口です。PHP の curl 拡張など、多くのプログラムが同じ libcurl を使っています
  • 歴史:1996年に始まった HttpGet・urlget を前身に、1998年3月20日に「curl 4」として公開されました(curl 公式の History)
  • ライセンス:curl 公式の Copyright ページでは「MIT/X をもとにしたが同一ではない」独自のライセンスで、無料で使えます
274オプションの数curl 8.23.0 の --help all
87終了コードの数0〜100 のうちマニュアルにあるもの
23使えたプロトコル今回ビルドした 8.23.0 の curl -V

最初の1行:curl URL を打つと何が起きるか

いちばん短い使い方は、URL を1つ渡すだけです。

$ curl http://localhost:40280/
<!doctype html><title>demo</title><h1>Hello curl</h1>

何もオプションを付けないと、curl は GET のリクエストを送り、返ってきた本文(ここでは HTML)をそのまま画面に出します。 ブラウザなら見出しとして描かれる HTML が、タグのまま見えます。API の URL なら JSON がそのまま出ます。

本文をファイルに保存すると、画面には進捗表示(プログレスメーター)が出ます。マニュアルによると、出力先が画面のときは本文と混ざらないように進捗表示を止めます。

$ curl -o page.html http://localhost:40280/
  % Total    % Received % Xferd  Average Speed  Time    Time    Time   Current
                                 Dload  Upload  Total   Spent   Left   Speed
100     54 100     54   0      0  75949      0                              0

進捗表示を消すのが -s(--silent)です。パイプで jq などに渡すときも進捗表示が出るので、-s を付けます。

curlとHTTPのやり取りの図

curl が HTTP で話すときの流れは次のとおりです。-v を付けたときに出る記号(* > < {)が、図のどこにあたるかも書き込みました。

%%{init: {'sequence': {'actorMargin': 20, 'width': 100}}}%%
sequenceDiagram
    participant C as curl
    participant S as サーバー
    Note over C: * 名前解決
    C->>S: * 接続(TCP・TLS)
    C->>S: > リクエスト行・ヘッダー
    C->>S: } 本文(POST のとき)
    S-->>C: < ステータス行・ヘッダー
    S-->>C: { 本文
    Note over C: 画面かファイルへ
  • リクエスト:メソッド(GET・POST など)、パス、ヘッダー、本文。curl のオプション -X・-H・-d・--json で決めます
  • レスポンス:ステータスコード(200・404 など)、ヘッダー、本文。-i・-o・-w で見せ方を決めます

curlでできること

1API の動作確認

GET・POST・PUT・DELETE を送り、JSON の結果を見る。ヘッダーやトークンも付けられる。

2ファイルのダウンロード

URL のファイル名で保存、途中からの再開、連番のまとめ取りができる。

3疎通・死活の確認

ステータスコードと応答時間だけを出し、監視やデプロイ後の確認に使う。

4通信の調査

-v で TLS・ヘッダー・リダイレクトの中身を見て、つながらない原因を探す。

5アップロード

フォームと同じ形(multipart)や PUT でファイルを送る。

6HTTP 以外の転送

FTP・SFTP・SMTP・WebSocket なども、ビルドが対応していれば扱える。

curlが入っている環境とバージョンの確かめ方

環境 入っているか 出典・確かめ方
Windows 10・11 標準で入っている(curl.exe) curl 公式・Microsoft Learn
macOS OS に同梱されている everything curl(curl 公式の本)
Linux 多くは入っている。無ければ apt install curl など everything curl

使えるオプションや機能は、curl の版とビルドで変わります。 まず curl -V(--version)で確かめます。

$ curl -V
curl 8.23.0 (x86_64-pc-linux-gnu) libcurl/8.23.0 OpenSSL/3.0.13 zlib/1.3 brotli/1.1.0 nghttp2/1.59.0
Release-Date: 2026-10-14
Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns mqtt mqtts pop3 pop3s rtsp smtp smtps telnet tftp ws wss
Features: alt-svc AsynchDNS brotli HSTS HTTP2 HTTPS-proxy IPv6 Largefile libz SSL threadsafe UnixSockets
  • 1行目:curl と libcurl の版、TLS のライブラリ(OpenSSL など)
  • Protocols:使えるプロトコル
  • Features:使える機能。HTTP2 があれば HTTP/2、HTTP3 があれば HTTP/3 が使える

同じ Linux でも、OS の apt で入る curl は版が違います。

環境 curl の版 確かめ方
curl 公式の最新版 8.23.0(2026-10-14) 公式の変更履歴(2026年10月24日時点)
Ubuntu 24.04 の apt 版 8.5.0(修正を当てた 8.5.0-2ubuntu10.15) curl -V の出力
Windows 10・11 の同梱版 公式ページの例では 8.13.0 curl 公式の Windows 向けの説明

curl -v の読み方(-i・-I との違い)

この節では、-v の出力の1行ずつの意味と、ヘッダーを見る3つのオプションの使い分けが分かります。

-v(--verbose)は、curl とサーバーのやり取りを全部見せるオプションです。 つながらない・思った結果が返らないときに、最初に付けます。マニュアルでは、行の先頭の記号が次の意味です。

記号 意味(マニュアルの原文) 出る内容の例
* additional info provided by curl 名前解決・接続・TLS・使った HTTP の版
> header sent by curl 送ったリクエスト行とヘッダー
< header received by curl 受け取ったステータス行とヘッダー
} data sent by curl 送った本文のバイト数
{ data received by curl 受け取った本文のバイト数

HTTP の -v を1行ずつ読む

$ curl -v http://localhost:40280/
* Host localhost:40280 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying 127.0.0.1:40280...
* Established connection to localhost (127.0.0.1 port 40280) from 127.0.0.1 port 34670
* using HTTP/1.x
> GET / HTTP/1.1
> Host: localhost:40280
> User-Agent: curl/8.23.0
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< Server: demo/1.0
< Date: Sat, 24 Oct 2026 01:34:46 GMT
< Content-Type: text/html; charset=utf-8
< Content-Length: 54
<
<!doctype html><title>demo</title><h1>Hello curl</h1>
* Connection #0 to host localhost:40280 left intact
行 読み方
Host ... was resolved 名前解決(DNS)ができた。ここで止まれば (6)
Trying 127.0.0.1:40280 その IP・ポートへ接続を始めた
Established connection TCP の接続ができた。ここで止まれば (7) か (28)
> GET / HTTP/1.1 送ったリクエスト行(メソッド・パス・版)
> Host > User-Agent > Accept curl が自動で付けたヘッダー
> だけの行 ヘッダーの終わり(空行)
< HTTP/1.1 200 OK サーバーが返したステータス
left intact 接続を閉じずに再利用できる状態で終わった

HTTPS の -v で TLS と HTTP/2 を読む

HTTPS では、接続のあとに TLS のハンドシェイクと証明書の確認が入ります(一部省略)。

$ curl -v --cacert ca.pem https://localhost:40443/echo -o /dev/null
*   Trying 127.0.0.1:40443...
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* SSL Trust Anchors:
*   CAfile: ca.pem
*   CApath: /etc/ssl/certs
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / X25519 / RSASSA-PSS
* ALPN: server accepted h2
* Server certificate:
*   subject: CN=localhost
*   start date: Oct 24 01:21:17 2026 GMT
*   expire date: Nov 23 01:21:17 2026 GMT
*   issuer: CN=RJC Demo CA
*   subjectAltName: "localhost" matches cert's "localhost"
* OpenSSL verify result: 0
* SSL certificate verified via OpenSSL.
* using HTTP/2
> GET /echo HTTP/2
> Host: localhost:40443
> User-Agent: curl/8.23.0
> Accept: */*
>
< HTTP/2 200
< server: nginx/1.24.0 (Ubuntu)
< content-type: application/json
< content-length: 128
  • SSL Trust Anchors:どの CA 証明書で相手を確かめたか
  • ALPN: server accepted h2:何も指定しなくても HTTP/2 で話した
  • Server certificate:相手の証明書の名前・期限・発行者。(60) のエラーはここで起きる
  • OpenSSL verify result: 0:検証に成功(0 以外ならその番号が原因)

-vv で時刻と送った本文まで見る

マニュアルによると、8.10 以降は -vv で時刻と転送の番号が付き、-vvv で送受信の中身まで出ます(以下は一部省略)。

$ curl -s -vv --json '{"name":"山田"}' http://localhost:40280/echo -o /dev/null
10:27:19.969192 [0-0] *   Trying 127.0.0.1:40280...
10:27:19.969452 [0-0] > POST /echo HTTP/1.1
10:27:19.969452 [0-0] > Host: localhost:40280
10:27:19.969452 [0-0] > User-Agent: curl/8.23.0
10:27:19.969452 [0-0] > Content-Type: application/json
10:27:19.969452 [0-0] > Accept: application/json
10:27:19.969452 [0-0] > Content-Length: 17
10:27:19.969466 [0-0] } [17 bytes data]
10:27:19.970241 [0-0] < HTTP/1.1 200 OK
10:27:19.970380 [0-0] { [200 bytes data]

送った本文の中身まで文字で見たいときは --trace-ascii - です(一部省略)。

$ curl -s --trace-ascii - http://localhost:40280/echo -d x=1 -o /dev/null
=> Send header, 152 bytes (0x98)
0000: POST /echo HTTP/1.1
0015: Host: localhost:40280
002c: User-Agent: curl/8.23.0
0045: Accept: */*
0052: Content-Length: 3
0065: Content-Type: application/x-www-form-urlencoded
0096:
=> Send data, 3 bytes (0x3)
0000: x=1

-i・-I・-v の違い

オプション 送るメソッド 出るもの
-i(--show-headers) そのまま(GET など) レスポンスヘッダー+本文
-I(--head) HEAD レスポンスヘッダーだけ
-v(--verbose) そのまま 接続・TLS・送ったヘッダー・受け取ったヘッダー+本文

curl -i は「本文の前にレスポンスヘッダーも出す」という意味です。 8.10.0 で長い名前が --include から --show-headers に変わりました。前の名前も使えます。

$ curl -i http://localhost:40280/status/404
HTTP/1.1 404 Not Found
Server: demo/1.0
Date: Sat, 24 Oct 2026 01:24:22 GMT
Content-Type: application/json
Content-Length: 38

{"status": 404, "error": "demo error"}

-I は HEAD リクエストなので本文は返りません。GET と HEAD で動きが違うサーバーもあるため、GET のヘッダーだけを見たいときは、本文を捨てて -D - でヘッダーを出す形が使えます。

$ curl -s -D - -o /dev/null http://localhost:40280/echo
HTTP/1.1 200 OK
Server: demo/1.0
Date: Sat, 24 Oct 2026 01:24:22 GMT
Content-Type: application/json
Content-Length: 105

curlのオプション一覧(目的別の早見表と用途別の一覧)

この節では、目的からオプションを引く早見表と、よく使う約70個の一覧が分かります。

全オプションは curl --help all で出せます。 curl 8.23.0 では 274 個、Ubuntu 24.04 の 8.5.0 では 258 個でした。curl --help だけだと、よく使う十数個とカテゴリの一覧が出ます。カテゴリを指定すると絞り込めます。

$ curl --help category
 auth        Authentication methods
 connection  Manage connections
 http        HTTP and HTTPS protocol
 output      File system output
 post        HTTP POST specific
 proxy       Options for proxies
 tls         TLS/SSL related
 ...
$ curl --help -i
    -i, --show-headers
        (HTTP FTP)  Show  response headers  in  the output.  HTTP  response
        headers can include things like  server name, cookies, date of  the
        document, HTTP  version  and  more. ...

curl --help http のように書くとカテゴリの一覧、curl --help -i のように書くと1つのオプションの説明が出ます。

目的別の早見表

目的 オプション 例
メソッドを変える -X -X PUT
ヘッダーを付ける -H -H 'Accept: application/json'
JSON を送る --json --json '{"a":1}'
フォームの値を送る -d -d 'name=yamada'
ファイルを送る -F・-T -F 'file=@a.jpg'
保存する -o・-O・-LO -o out.json
ヘッダーを見る -i・-I・-D - -i
やり取りを全部見る -v・--trace-ascii -v
進捗を消す -s・-sS -sS
ステータス・時間を出す -w -w '%{http_code}'
リダイレクトをたどる -L・--follow -L
認証 -u・--oauth2-bearer -u user:pass
Cookie -b・-c -c jar.txt
失敗を検知する -f・--fail-with-body --fail-with-body
時間の上限・再試行 -m・--retry -m 10 --retry 3
証明書 --cacert・-k --cacert ca.pem
プロキシ -x・--noproxy -x http://proxy:8080

以下は用途別の一覧です。短い形(-o)と長い形(--output)は同じ意味です。 「追加」の列は、curl のドキュメントに書かれた、そのオプションが入った版です。

リクエストを組み立てる

短い形 長い形 意味 例 追加
-X --request メソッドを指定 -X PUT 6.0
-H --header リクエストヘッダーを付ける -H 'Accept: application/json' 5.0
-d --data 本文を送る(POST になる) -d 'name=yamada' 4.0
なし --data-raw @ をファイル指定と見なさずに送る --data-raw '@home' 7.43.0
なし --data-binary 改行などを変えずにそのまま送る --data-binary @a.bin 7.2
なし --data-urlencode URL エンコードして送る --data-urlencode 'q=東京 駅' 7.18.0
なし --json JSON を POST(ヘッダー2つを自動で付ける) --json '{"a":1}' 7.82.0
-F --form multipart/form-data で送る -F 'file=@photo.jpg' 5.0
-G --get -d の内容を URL のクエリにして GET -G -d 'page=2' 7.8.1
なし --url-query URL にクエリを足す --url-query 'q=東京' 7.87.0
-T --upload-file ファイルを PUT でアップロード -T data.csv 4.0
-A --user-agent User-Agent を変える -A 'MyApp/1.0' 4.5.1
-e --referer Referer を付ける -e 'https://example.com/' 4.0
なし --compressed 圧縮して受け取り、展開して出す --compressed 7.10
-r --range 範囲を指定して一部だけ取る -r 0-99 4.0

表示・出力

短い形 長い形 意味 例 追加
-i --show-headers レスポンスヘッダーも出す(旧名 --include) curl -i URL 4.8
-I --head HEAD を送り、ヘッダーだけ出す curl -I URL 4.0
-v --verbose 送受信の詳細を出す curl -v URL 4.0
なし --trace-ascii 送受信の全データを記録 --trace-ascii log.txt 7.9.7
-s --silent 進捗とエラー表示を消す curl -s URL 4.0
-S --show-error -s でもエラーは出す curl -sS URL 5.9
なし --no-progress-meter 進捗表示だけ消す --no-progress-meter 7.67.0
-o --output ファイルに保存 -o result.json 4.0
-O --remote-name URL のファイル名で保存 -O 4.0
-J --remote-header-name サーバーが示すファイル名で保存 -OJ 7.20.0
なし --output-dir 保存先のディレクトリ --output-dir dl 7.73.0
なし --create-dirs 保存先のディレクトリを作る -o a/b/c.txt --create-dirs 7.10.3
-D --dump-header 受け取ったヘッダーをファイルへ -D headers.txt 5.7
-w --write-out 終了後に情報を出す -w '%{http_code}' 6.5
なし --out-null 本文を捨てる(-o /dev/null の代わり) --out-null 8.16.0
-# --progress-bar 進捗を棒グラフで出す -# 5.10

リダイレクト・ダウンロード

短い形 長い形 意味 例 追加
-L --location リダイレクトをたどる curl -L URL 4.9
なし --follow 仕様どおりにメソッドを変えてたどる --follow -X POST 8.16.0
なし --max-redirs たどる回数の上限(既定 50) --max-redirs 5 7.5
-C --continue-at 途中から再開(- で自動) -C - 4.8
なし --no-clobber 同名ファイルを上書きしない --no-clobber -O 7.83.0
なし --skip-existing ファイルがあればダウンロードしない --skip-existing -O 8.10.0
なし --limit-rate 速度を制限する --limit-rate 1M 7.10
なし --etag-save ETag を保存する --etag-save etag.txt 7.68.0
なし --etag-compare 保存した ETag と比べて取得 --etag-compare etag.txt 7.68.0

認証・Cookie

短い形 長い形 意味 例 追加
-u --user ユーザー名とパスワード(Basic 認証) -u user:pass 4.0
なし --oauth2-bearer Bearer トークンを付ける --oauth2-bearer TOKEN 7.33.0
なし --anyauth サーバーに合わせて認証方式を選ぶ --anyauth -u user:pass 7.10.6
-b --cookie Cookie を送る(文字列かファイル) -b 'sid=abc' 4.9
-c --cookie-jar 受け取った Cookie を保存 -c cookies.txt 7.9
なし --location-trusted リダイレクト先の別ホストにも認証情報を送る --location-trusted 7.10.4

失敗の扱い・タイムアウト・再試行

短い形 長い形 意味 例 追加
-f --fail 400 以上を失敗(終了コード 22)にし、本文を出さない -f 4.0
なし --fail-with-body 400 以上を失敗にし、本文は出す --fail-with-body 7.76.0
-m --max-time 全体の制限時間(秒) -m 30 4.0
なし --connect-timeout 接続までの制限時間(秒) --connect-timeout 5 7.7
なし --retry 一時的なエラーで再試行する回数 --retry 3 7.12.3
なし --retry-delay 再試行の間隔(秒) --retry-delay 2 7.12.3
なし --retry-max-time 再試行を続ける上限時間(秒) --retry-max-time 60 7.12.3
なし --retry-connrefused 接続拒否でも再試行する --retry-connrefused 7.52.0
なし --retry-all-errors すべてのエラーで再試行する --retry-all-errors 7.71.0

TLS・証明書・接続先

短い形 長い形 意味 例 追加
-k --insecure 証明書の検証を省く -k 7.10
なし --cacert 信頼する CA 証明書を指定 --cacert ca.pem 7.5
なし --ca-native OS の証明書ストアを使う --ca-native 8.2.0
なし --http1.1 HTTP/1.1 を使う --http1.1 7.33.0
なし --http2 HTTP/2 を使う --http2 7.33.0
なし --http3 HTTP/3 を試す(つながらなければ HTTP/2 などへ) --http3 7.66.0
なし --http3-only HTTP/3 だけを使う --http3-only 7.88.0
-x --proxy プロキシを使う -x http://proxy:8080 4.0
なし --noproxy プロキシを使わないホスト --noproxy localhost 7.19.4
なし --resolve 名前解決の結果を指定 --resolve host:443:10.0.0.5 7.21.3
なし --connect-to 別のホスト・ポートへ接続 --connect-to host:443:stg:8443 7.49.0
-4 / -6 --ipv4 / --ipv6 IPv4・IPv6 だけを使う -4 7.10.8

並列・変数・設定ファイル

短い形 長い形 意味 例 追加
-Z --parallel 複数の URL を並列に転送 -Z URL1 URL2 7.66.0
なし --parallel-immediate 多重化を待たずに接続を増やす -Z --parallel-immediate 7.68.0
なし --variable 変数を定義(環境変数も取り込める) --variable %API_TOKEN 8.3.0
なし --expand-(オプション名) オプションの中で {{変数}} を展開 --expand-header 8.3.0
-K --config オプションをファイルから読む -K api.curlrc 4.10
-V --version 版と機能を表示 -V 4.0
-h --help ヘルプ(all で全部) --help all 4.0

curlでAPIを確認する:GET・POST・JSON・ヘッダー・認証・Cookie

この節では、API の確認でよく使う8つの送り方と、サーバーが実際に受け取った中身が分かります。

テスト用サーバーの /echo と /api/... は、受け取ったメソッド・パス・ヘッダー・本文をそのまま JSON で返します。curl が実際に何を送ったかが見えます。

GET

$ curl http://localhost:40280/echo
{"method": "GET", "path": "/echo", "headers": {"user-agent": "curl/8.23.0", "accept": "*/*"}, "body": ""}

POST(フォーム形式)

$ curl -d 'name=yamada&age=30' http://localhost:40280/echo
{"method": "POST", "path": "/echo", "headers": {"user-agent": "curl/8.23.0", "accept": "*/*", "content-length": "18", "content-type": "application/x-www-form-urlencoded"}, "body": "name=yamada&age=30"}

-d を付けると、自動で POST になり、Content-Type は application/x-www-form-urlencoded になりました。 -X POST は書かなくても POST です。

JSON を POST する(--json)

$ curl --json '{"name":"山田"}' http://localhost:40280/echo
{"method": "POST", "path": "/echo", "headers": {"user-agent": "curl/8.23.0", "content-type": "application/json", "accept": "application/json", "content-length": "17"}, "body": "{\"name\":\"山田\"}"}

--json(7.82.0 以降)は、ドキュメントでは次の3つをまとめたものです。7.82.0 より前の curl では、この3つを自分で書きます。

--data-binary '{"name":"山田"}' -H 'Content-Type: application/json' -H 'Accept: application/json'

中身が正しい JSON かどうかを curl は確かめません。 長い JSON はファイルに書いて @ で読むと、引用符で迷いません。

$ curl -s --json @user.json http://localhost:40280/echo
{"method": "POST", "path": "/echo", "headers": {"user-agent": "curl/8.23.0", "content-type": "application/json", "accept": "application/json", "content-length": "34"}, "body": "{\"name\":\"山田\",\"tags\":[\"a\",\"b\"]}"}

レスポンスの JSON は、jq に渡すと整形・抽出できます。関連記事「jqの使い方|逆引き40例と実務レシピを全部実行結果つきで解説」で扱っています。

$ curl -s http://localhost:40280/api/users/1 | jq -r '.method, .path'
GET
/api/users/1

PUT・PATCH・DELETE

$ curl -X PUT --json '{"name":"佐藤"}' http://localhost:40280/api/users/1
{"method": "PUT", "path": "/api/users/1", ..., "body": "{\"name\":\"佐藤\"}"}

$ curl -X PATCH --json '{"age":31}' http://localhost:40280/api/users/1
{"method": "PATCH", "path": "/api/users/1", ..., "body": "{\"age\":31}"}

$ curl -X DELETE http://localhost:40280/api/users/1
{"method": "DELETE", "path": "/api/users/1", "headers": {"user-agent": "curl/8.23.0", "accept": "*/*"}, "body": ""}

--json と -X PUT を組み合わせると、JSON の PUT になりました。メソッドごとの意味の違いは、関連記事「HTTPメソッド一覧|GET・POST・PUT・PATCHの違い早見表」で扱っています。

ヘッダーを付ける・消す

$ curl -H 'Authorization: Bearer TOKEN123' -H 'X-Request-Id: 42' http://localhost:40280/echo
{"method": "GET", "path": "/echo", "headers": {"user-agent": "curl/8.23.0", "accept": "*/*", "authorization": "Bearer TOKEN123", "x-request-id": "42"}, "body": ""}

$ curl -H 'Accept:' -H 'User-Agent;' http://localhost:40280/echo
{"method": "GET", "path": "/echo", "headers": {"user-agent": ""}, "body": ""}

-H 'Accept:' のように値を空にすると、curl が自動で付けるヘッダーが消えました。-H 'User-Agent;'(コロンではなくセミコロン)は、値が空のヘッダーを送ります。

認証(Basic・Bearer トークン)

$ curl -s -u user:pass http://localhost:40280/basic
{"auth": "ok"}
$ curl -s -u user:wrong -w ' %{http_code}\n' http://localhost:40280/basic
{"error": "unauthorized"} 401

$ curl -s --oauth2-bearer TOKEN123 http://localhost:40280/bearer
{"auth": "ok"}
$ curl -s -H 'Authorization: Bearer WRONG' -w ' %{http_code}\n' http://localhost:40280/bearer
{"error": "invalid token"} 401

--oauth2-bearer TOKEN は -H 'Authorization: Bearer TOKEN' と同じヘッダーになりました。-u user のようにパスワードを省くと、curl が入力を求めます。コマンドにパスワードやトークンを直接書くと、シェルの履歴に残ります。 環境変数から入れる方法は、後の「--variable」の節にあります。

Cookie(ログインの状態を保つ)

$ curl -s -c cookies.txt http://localhost:40280/login
{"login": "ok"}
$ curl -s -b cookies.txt http://localhost:40280/mypage
{"user": "yamada"}
$ curl -s http://localhost:40280/mypage
{"error": "login required"}
$ grep sid cookies.txt
#HttpOnly_localhost FALSE   /   FALSE   0   sid abc123

-c で受け取った Cookie をファイルに保存し、-b でそのファイルを読むと、ログイン後のページが返りました。-b を付けないと 401 です。保存されたファイルには Cookie の値がそのまま入るので、人に渡さないように扱います。

クエリ文字列を付ける(日本語・空白)

$ curl -G --data-urlencode 'q=東京 駅' -d page=2 http://localhost:40280/echo
{"method": "GET", "path": "/echo?q=%E6%9D%B1%E4%BA%AC+%E9%A7%85&page=2", ...}

$ curl --url-query 'q=東京 駅' http://localhost:40280/echo
{"method": "GET", "path": "/echo?q=%E6%9D%B1%E4%BA%AC+%E9%A7%85", ...}

$ curl 'http://localhost:40280/echo?q=東京 駅'
curl: (3) URL rejected: Bad query

URL に空白をそのまま書くと、8.23.0 では URL rejected: Bad query、8.5.0 では URL rejected: Malformed input to a URL function になりました。日本語や空白は --data-urlencode か --url-query でエンコードします。

ステータスコード・応答時間を表示する(-w の変数一覧)

この節では、-w でステータスコード・応答時間・ヘッダーの値だけを取り出す方法が分かります。

-w(--write-out)は、転送が終わった後に、指定した情報を出します。監視やデプロイ後の確認で、いちばんよく使う組み合わせはこれです。

$ curl -s -o /dev/null -w '%{http_code}\n' http://localhost:40280/echo
200
  • -s:進捗表示を消す
  • -o /dev/null:本文を捨てる(Windows では -o nul。8.16.0 以降は --out-null でも同じ)
  • -w '%{http_code}\n':ステータスコードを出す

ステータスコードごとの意味は、関連記事「HTTPステータスコード 一覧|全コードの原因と対処・curl実例つき」で扱っています。

よく使う変数

変数 意味 実行した値の例
%{http_code} ステータスコード(接続できないと 000) 404
%{http_version} 実際に使った HTTP の版 2
%{remote_ip} / %{remote_port} 接続先の IP とポート 127.0.0.1:40443
%{size_download} 受け取った本文のバイト数 128
%{content_type} Content-Type application/json
%{redirect_url} リダイレクト先(-L なしのとき) http://localhost:40280/redirect/2
%{num_redirects} たどったリダイレクトの回数 3
%{url_effective} 最後にアクセスした URL http://localhost:40280/echo
%{num_retries} 再試行した回数(8.9.0) 2
%{exitcode} / %{errormsg} 終了コードとエラー文(7.75.0) 7 / Failed to connect ...
%{onerror} ここから後ろは失敗したときだけ出す(7.75.0) なし
%header{名前} レスポンスヘッダーの値(7.84.0) demo/1.0
%{json} すべての変数を JSON で出す(7.70.0) 下の例
%output{ファイル} ここから後ろをファイルに書く(8.3.0) %output{>>stats.log} で追記
%time{書式} 現在の UTC 時刻(8.16.0) 2026-10-24 01:24:42

応答時間を区間ごとに測る

$ curl -s -o /dev/null --cacert ca.pem \
  -w 'DNS:%{time_namelookup} 接続:%{time_connect} TLS:%{time_appconnect} 最初の応答:%{time_starttransfer} 合計:%{time_total}\n' \
  'https://localhost:40443/slow?sec=0.3'
DNS:0.000021 接続:0.000107 TLS:0.002070 最初の応答:0.303173 合計:0.303227

0.3 秒待ってから返すように作った URL では、最初の応答 だけが 0.3 秒増えました。接続・TLS までが短く、最初の応答までが長ければ、サーバー側の処理に時間がかかっています。

変数 開始から、いつまでの秒数か
time_namelookup 名前解決(DNS)が終わるまで
time_connect TCP 接続が終わるまで
time_appconnect TLS のハンドシェイクが終わるまで
time_pretransfer 転送を始める直前まで
time_starttransfer 最初の1バイトを受け取るまで
time_total 全体

失敗したときだけエラーを出す(%{onerror})

$ curl -s -o /dev/null -w '%{http_code}\n%{onerror}エラー:%{exitcode} %{errormsg}\n' http://localhost:40280/echo
200

$ curl -s -o /dev/null -w '%{http_code}\n%{onerror}エラー:%{exitcode} %{errormsg}\n' http://localhost:1/
000
エラー:7 Failed to connect to localhost:1 after 0 ms: Could not connect to server

ヘッダーの値・全項目を JSON で出す

$ curl -s -o /dev/null -w '%header{content-type} / %header{server}\n' http://localhost:40280/echo
application/json / demo/1.0

$ curl -s -o /dev/null -w '%{json}' http://localhost:40280/status/404 | jq '{http_code, http_version, num_connects, size_download, time_total}'
{
  "http_code": 404,
  "http_version": "1.1",
  "num_connects": 1,
  "size_download": 38,
  "time_total": 0.000556
}

%{json} は、8.23.0 では 69 項目、8.5.0 では 63 項目の JSON になりました。

ファイルのダウンロードとアップロード

この節では、保存の名前の決まり方、再開、連番、圧縮、アップロードの書き方が分かります。

-O・-o・-LO(curl -lo の意味)

$ curl -s -O http://localhost:40280/files/report.txt && ls -l report.txt
-rw-r--r-- 1 root root 12000 Oct 24 10:25 report.txt

$ curl -s -o out/latest.txt --create-dirs http://localhost:40280/files/report.txt && ls -l out
total 12
-rw-r--r-- 1 root root 12000 Oct 24 10:25 latest.txt

curl -LO URL は -L(リダイレクトをたどる)と -O(URL のファイル名で保存)を並べた形です。 GitHub のリリースのように、リダイレクトの先にファイルがある URL でよく使います。小文字の -l は FTP の --list-only で、意味が違います。

書き方 保存される名前
-o 名前 指定した名前
-O URL の最後の部分(report.txt)
-OJ サーバーの Content-Disposition の名前(report-2026.txt)
-O --no-clobber(8.23.0) 同名があれば report-1.txt、report-2.txt
-O --no-clobber(8.5.0) 同名があれば report.txt.1
-O --skip-existing 同名があれば取りに行かない(000 0)
$ curl -s -OJ http://localhost:40280/download -w '%{filename_effective}\n'
report-2026.txt

$ curl -s -O --no-clobber http://localhost:40280/files/report.txt && ls report*
report-1.txt
report.txt

--no-clobber の連番の付き方は 8.23.0 で変わりました。 公式の変更履歴では「inject the no-clobber number before the extension」で、拡張子の前に番号が入ります。8.5.0 では report.txt.1 でした。

途中から再開する(-C -)

$ head -c 5000 report.txt > partial.txt
$ curl -s -C - -o partial.txt http://localhost:40280/files/report.txt -w '%{http_code} %{size_download}\n'
206 7000
$ wc -c partial.txt
12000 partial.txt

5000 バイトまであるファイルに対して、残りの 7000 バイトだけを受け取り(206 Partial Content)、12000 バイトのファイルになりました。

連番・まとめて取る(URL のグロブ)

$ curl -s -o 'page_#1.json' 'http://localhost:40280/api/users/[1-3]' && ls page_*
page_1.json
page_2.json
page_3.json
書き方 意味
[1-3] 1・2・3
[001-100] 001〜100(桁をそろえる)
[a-z] a〜z
{users,orders} 列挙したものを順に
#1・#2 1つ目・2つ目の [] {} に当てはまった値

-g(--globoff)を付けると、[] {} を文字としてそのまま送ります。

圧縮して受け取る(--compressed)

コマンド 受け取ったバイト数(%{size_download}) 画面に出たバイト数
curl URL 6000 6000
curl --compressed URL 42 6000

アップロード(-F・-T)

$ curl -s -F 'file=@photo.jpg' -F 'title=写真' http://localhost:40280/upload
{"content-type": "multipart/form-data; boundary=------------------------qNSLUhXvsWiTNOpFpIpVp5", "bytes": 605}

$ curl -s -T report.txt http://localhost:40280/echo | jq -c '{method, len: .headers["content-length"]}'
{"method":"PUT","len":"12000"}

-F は、HTML のフォームからファイルを送るときと同じ multipart/form-data で送ります。-T ファイル は本文にファイルをそのまま入れて PUT しました。

スクリプトやCIでの使い方:--fail・タイムアウト・再試行

この節では、curl をシェルスクリプトや CI に入れるときに、失敗を見逃さない書き方が分かります。

404 や 500 でも「成功」になる

curl は、404 や 500 が返っても、通信が終わっていれば終了コード 0(成功)で終わります。 スクリプトや CI では、エラーに気づけません。

$ curl -s http://localhost:40280/status/404; echo " 終了コード=$?"
{"status": 404, "error": "demo error"} 終了コード=0

$ curl -s -f http://localhost:40280/status/404; echo "終了コード=$?"
終了コード=22

$ curl -sS -f http://localhost:40280/status/404; echo "終了コード=$?"
curl: (22) The requested URL returned error: 404
終了コード=22

$ curl -sS --fail-with-body http://localhost:40280/status/404; echo " 終了コード=$?"
curl: (22) The requested URL returned error: 404
{"status": 404, "error": "demo error"} 終了コード=22
書き方 本文 エラー文 終了コード
オプションなし 出る 出ない 0
-s -f 出ない 出ない 22
-sS -f 出ない 出る 22
-sS --fail-with-body 出る 出る 22

スクリプトでは -sS --fail-with-body が扱いやすい組み合わせです。 進捗は消え、エラー文とサーバーが返したエラーの本文は残り、失敗は失敗として終わります。終了コードは $? で取れるので、if curl ...; then の形で成功と失敗を分けられます。

タイムアウト

$ curl -sS --max-time 2 http://localhost:40281/; echo "終了コード=$?"
curl: (28) Operation timed out after 2001 milliseconds with 0 bytes received
終了コード=28

接続は受け付けるが何も返さないサーバーに向けると、--max-time 2 で 2 秒後に終わりました。タイムアウトを指定しないと、このような相手には待ち続けます。 --connect-timeout は接続までの上限、--max-time は全体の上限です。

再試行(--retry)

ドキュメントでは、--retry が再試行するのは「一時的なエラー」だけです。タイムアウト、FTP の 4xx、HTTP の 408・429・500・502・503・504・522・524 が対象で、待ち時間は1秒から倍々に増え、Retry-After ヘッダーがあれば従います。

3回に1回だけ 200 を返し、それ以外は 503 を返す URL で試しました。

$ curl --no-progress-meter --retry 3 -o /dev/null -w '%{http_code} retries=%{num_retries}\n' http://localhost:40280/flaky
Warning: Problem : HTTP error. Retrying in 1 second. 3 retries left.
Warning: Problem : HTTP error. Retrying in 1 second. 2 retries left.
200 retries=2
状況 --retry 2 だけ 足すオプション
503 が返る 再試行した なし
接続拒否(終了コード 7) 再試行しなかった(retries=0) --retry-connrefused で 2 回再試行
404 が返る 再試行しなかった(終了コード 0) --retry-all-errors -f で 2 回再試行

--retry-all-errors は、ドキュメントで「大ハンマー」と書かれ、データの二重送信が起こりうるため、既定の設定に入れないよう注意されています。POST を送る API には向きません。

設定ファイル(-K)でオプションをまとめる

$ cat api.curlrc
silent
show-error
fail-with-body
max-time = 10
header = "Accept: application/json"

$ curl -K api.curlrc http://localhost:40280/status/500; echo " exit=$?"
curl: (22) The requested URL returned error: 500
{"status": 500, "error": "demo error"} exit=22

設定ファイルでは、長い形のオプション名から -- を取って書きます。

スクリプトに入れる前のチェック

  • 14xx・5xx を失敗として扱っている-f か --fail-with-body を付ける。無いと 404 でも終了コード 0
  • 2進捗は消し、エラー文は残している-s だけでなく -sS にする
  • 3時間の上限がある--max-time と --connect-timeout。無いと応答しない相手を待ち続ける
  • 4再試行は、二重に送って困らない処理だけにしているPOST に --retry-all-errors を付けない
  • 5証明書の検証を省いていない-k を残さず、--cacert か --ca-native を使う
  • 6トークンやパスワードをコマンドに直接書いていない環境変数と --variable、または -K の設定ファイルから読む

新しい版で増えたオプション(--json・--variable・--follow など)

この節では、ここ数年の版で入った、API の確認やスクリプトで役に立つ機能が分かります。

curl は、通常8週間ごとに新しい版が出ます(curl のリリース手順書)。

版 追加・変更された主なもの
7.82.0 --json
7.83.0 --no-clobber、-w '%{header_json}'
7.84.0 -w '%header{名前}'
7.87.0 --url-query
8.2.0 --ca-native
8.3.0 --variable と --expand-*、-w '%output{}'
8.9.0 -w '%{num_retries}'
8.10.0 --skip-existing、-i の長い名前が --show-headers に
8.16.0 --follow、--out-null、-w '%time{}'
8.22.0 HTTP Message Signatures(RFC 9421)への対応、TLS-SRP の削除
8.23.0 --no-clobber の番号を拡張子の前に、SMB の削除

Ubuntu 24.04 の curl 8.5.0 では、--out-null は option --out-null: is unknown になりました。 使う前に curl -V で版を確かめます。

--variable:環境変数を安全に埋め込む(8.3.0)

--variable %名前 で環境変数を取り込み、--expand- を付けたオプションの中で {{名前}} として使えます。

$ export API_TOKEN=secret-123
$ curl -s --variable %API_TOKEN --expand-header 'Authorization: Bearer {{API_TOKEN}}' http://localhost:40280/echo
{"method": "GET", "path": "/echo", "headers": {"user-agent": "curl/8.23.0", "accept": "*/*", "authorization": "Bearer secret-123"}, "body": ""}

環境変数が無いときは、エラーで止まりました。%名前=既定値 と書くと、無いときに既定値を使います。

$ curl -s --variable %NOPE http://localhost:40280/echo
curl: option --variable: variable expansion failure

$ curl -s --variable %ENVNAME=dev --expand-url 'http://localhost:40280/api/{{ENVNAME}}/health'
{"method": "GET", "path": "/api/dev/health", ...}

{{名前:url}} は URL エンコード、{{名前:json}} は JSON の文字列としてエスケープします。JSON に " を含む値を埋め込んでも、壊れませんでした。

$ curl -s --variable 'name=山田 太郎' --expand-url 'http://localhost:40280/echo?q={{name:url}}'
{"method": "GET", "path": "/echo?q=%E5%B1%B1%E7%94%B0%20%E5%A4%AA%E9%83%8E", ...}

$ curl -s --variable 'msg=He said "hi"' --expand-json '{"text":"{{msg:json}}"}' http://localhost:40280/echo
{"method": "POST", ..., "body": "{\"text\":\"He said \\\"hi\\\"\"}"}

--follow と -L の違い(8.16.0)

301・302・303・307・308 のリダイレクトを返す URL に、3つの書き方で POST を送り、転送先が受け取ったものを比べました。

コマンド 301・302・303 のとき 307・308 のとき
-L -d 'a=1' GET(本文なし) POST(本文 a=1)
-L -X POST -d 'a=1' POST(本文なし) POST(本文 a=1)
--follow -X POST -d 'a=1' GET(本文なし) POST(本文 a=1)
$ curl -s -L -X POST -d 'a=1' http://localhost:40280/redirect/1
{"method": "POST", "path": "/echo", "headers": {"user-agent": "curl/8.23.0", "accept": "*/*"}, "body": ""}

$ curl -s --follow -X POST -d 'a=1' http://localhost:40280/redirect/1
{"method": "GET", "path": "/echo", "headers": {"user-agent": "curl/8.23.0", "accept": "*/*"}, "body": ""}

-L と -X POST を一緒に使うと、302 の転送先に「本文の無い POST」が送られました。 --follow は、HTTP の仕様どおり 301・302・303 では GET に変え、307・308 では POST のまま本文も送ります。-L はドキュメントのとおり、-u などの認証情報を最初のホストにしか送りません。別のホストにも送るのが --location-trusted です。

--parallel:複数の URL を同時に取る

1秒かかる URL を3つ取ったときの時間です。

コマンド 全体の時間
オプションなし(順番に取る) 3.096 秒
-Z 2.052 秒
-Z --parallel-immediate 1.011 秒
$ curl -s -Z --parallel-immediate -w '%{http_code} %{time_total}\n' \
  -o /dev/null -o /dev/null -o /dev/null \
  'http://localhost:40280/slow?sec=1' 'http://localhost:40280/slow?sec=1' 'http://localhost:40280/slow?sec=1'
200 1.000968
200 1.001221
200 1.002059

-Z だけでは、同じホストへの2本目以降が待たされました。ドキュメントによると、-Z は HTTP/2 の多重化(1本の接続で複数を送る)に乗せられるかを待つためで、--parallel-immediate は待たずに接続を増やします。

HTTP/3(--http3)

--http3 は HTTP/3 を試し、つながらなければ HTTP/2・HTTP/1.1 に切り替えます。--http3-only は切り替えません。どちらも curl -V の Features に HTTP3 がある curl でだけ使えます。今回ビルドした curl には無いので、次のエラーになりました。

$ curl -sS --http3 https://localhost:40443/echo
curl: option --http3: the installed libcurl version does not support this

curlの終了コード一覧(全87個の原文)

この節では、curl: (番号) の番号が何を表すかを、マニュアルの原文と日本語で引けます。

curl は、失敗すると 0 以外の終了コードで終わり、エラー文の先頭に curl: (番号) を付けます。番号を見れば、どこで止まったかがおおよそ分かります。

flowchart TD
    A[curl: 番号 のエラー] --> B[6 名前解決<br>URLのつづり・DNS]
    B --> C[7 接続<br>起動・ポート・FW]
    C --> D[28 時間切れ<br>-w で区間を測る]
    D --> E[35・60 TLS・証明書<br>http/https・--cacert]
    E --> F[22 HTTPのエラー<br>-f のときの 4xx・5xx]

上から順に、通信の手前の段階で止まったものほど上にあります。下の表は、curl 8.23.0 のマニュアル(curl --manual の「EXIT CODES」)にある 87 個すべてです。原文は各項目の最初の1文です。マニュアルには「既存の番号は変わらない(The existing ones are meant to never change.)」と書かれています。

番号 原文(マニュアル) 意味
0 Success. 成功
1 Unsupported protocol. 対応していないプロトコル(URL のつづり違いなど)
2 Failed to initialize. 初期化の失敗(オプションの誤りなど)
3 URL malformed. URL の形式が正しくない
4 A feature or option that was needed to perform the desired request was not enabled or was explicitly disabled at build-time. 必要な機能がビルドに入っていない
5 Could not resolve proxy. プロキシの名前解決に失敗
6 Could not resolve host. ホストの名前解決に失敗
7 Failed to connect to host. ホストへの接続に失敗
8 Weird server reply. サーバーの応答を解釈できない
9 FTP access denied. FTP のアクセス拒否
10 FTP accept failed. FTP のアクティブ接続の受け付けに失敗
11 FTP weird PASS reply. FTP の PASS への応答が不正
12 During an active FTP session while waiting for the server to connect back to curl, the timeout expired. FTP のアクティブ接続でタイムアウト
13 FTP weird PASV reply, curl could not parse the reply sent to the PASV request. FTP の PASV への応答が不正
14 FTP weird 227 format. FTP の 227 行の形式が不正
15 FTP cannot use host. FTP の 227 行のホストを解決できない
16 HTTP/2 error. HTTP/2 のフレームの問題
17 FTP could not set binary. FTP でバイナリに切り替えられない
18 Partial file. ファイルの一部しか転送できなかった
19 FTP could not download/access the given file, the RETR (or similar) command failed. FTP の RETR などが失敗
21 FTP quote error. FTP の quote コマンドが失敗
22 HTTP page not retrieved. HTTP のエラー(400 以上。--fail のとき)
23 Write error. 書き込みエラー(保存先など)
25 Failed starting the upload. アップロードを始められない
26 Read error. 読み込みエラー
27 Out of memory. メモリ不足
28 Operation timeout. タイムアウト
30 FTP PORT failed. FTP の PORT が失敗
31 FTP could not use REST. FTP の REST が失敗
33 HTTP range error. HTTP の範囲指定(Range)が効かない
34 HTTP post error. HTTP の POST の組み立てで内部エラー
35 SSL connect error. TLS(SSL)の接続エラー
36 Bad download resume. ダウンロードの再開に失敗
37 FILE could not read file. FILE の URL のファイルを読めない
38 LDAP cannot bind. LDAP の bind が失敗
39 LDAP search failed. LDAP の検索が失敗
41 Function not found. LDAP の関数が見つからない
42 Aborted by callback. コールバックで中断された
43 Internal error. 内部エラー(関数に不正な引数)
45 Interface error. 指定した送信元インターフェースを使えない
47 Too many redirects. リダイレクトが多すぎる
48 Unknown option specified to libcurl. libcurl に不明なオプションを渡した
49 Malformed telnet option. telnet のオプションの形式が不正
52 The server did not reply anything, which here is considered an error. サーバーが何も返さなかった
53 SSL crypto engine not found. TLS の暗号エンジンが見つからない
54 Cannot set SSL crypto engine as default. TLS の暗号エンジンを既定にできない
55 Failed sending network data. ネットワークへの送信に失敗
56 Failure in receiving network data. ネットワークからの受信に失敗
58 Problem with the local certificate. 手元の証明書(クライアント証明書)の問題
59 Could not use specified SSL cipher. 指定した暗号スイートを使えない
60 Peer certificate cannot be authenticated with known CA certificates. サーバー証明書を既知の CA で検証できない
61 Unrecognized transfer encoding. 転送エンコーディングを認識できない
63 Maximum file size exceeded. ファイルの大きさの上限を超えた
64 Requested FTP SSL level failed. FTP の TLS の要求レベルを満たせない
65 Sending the data requires a rewind that failed. 再送のための巻き戻しに失敗
66 Failed to initialize SSL Engine. TLS エンジンの初期化に失敗
67 The username, password, or similar was not accepted and curl failed to log in. ユーザー名・パスワードなどが通らずログインできない
68 File not found on TFTP server. TFTP サーバーにファイルが無い
69 Permission problem on TFTP server. TFTP サーバーの権限の問題
70 Out of disk space on TFTP server. TFTP サーバーのディスクがいっぱい
71 Illegal TFTP operation. TFTP の不正な操作
72 Unknown TFTP transfer ID. TFTP の転送 ID が不明
73 File already exists (TFTP). TFTP でファイルがすでにある
74 No such user (TFTP). TFTP でユーザーが無い
77 Problem reading the SSL CA cert (path? access rights?). CA 証明書を読み込めない(パス・権限)
78 The resource referenced in the URL does not exist. URL が指すリソースが無い
79 An unspecified error occurred during the SSH session. SSH のセッションで不明なエラー
80 Failed to shut down the SSL connection. TLS の接続の終了に失敗
82 Could not load CRL file, missing or wrong format. CRL ファイルを読み込めない
83 Issuer check failed. 発行者の確認に失敗
84 The FTP PRET command failed. FTP の PRET が失敗
85 Mismatch of RTSP CSeq numbers. RTSP の CSeq 番号が合わない
86 Mismatch of RTSP Session Identifiers. RTSP のセッション ID が合わない
87 Unable to parse FTP file list. FTP のファイル一覧を解釈できない
88 FTP chunk callback reported error. FTP のチャンクのコールバックがエラー
89 No connection available, the session is queued. 使える接続が無く、順番待ち
90 SSL public key does not match pinned public key. 公開鍵がピン留めした鍵と合わない
91 Invalid SSL certificate status. 証明書の状態(OCSP)が不正
92 Stream error in HTTP/2 framing layer. HTTP/2 のストリームのエラー
93 An API function was called from inside a callback. コールバックの中から API を呼んだ
94 An authentication function returned an error. 認証の関数がエラーを返した
95 A problem was detected in the HTTP/3 layer. HTTP/3 の層の問題
96 QUIC connection error. QUIC の接続エラー
97 Proxy handshake error. プロキシのハンドシェイクのエラー
98 A client-side certificate is required to complete the TLS handshake. TLS にクライアント証明書が必要
99 Poll or select returned fatal error. poll・select が致命的なエラー
100 A value or data field grew larger than allowed. 値やデータが許される大きさを超えた

番号の付いていない curl: option ... のエラー(オプションの書き間違い・使えないオプション)は、終了コード 2 でした。

curlのよくあるエラーと直し方

この節では、よく出るエラー文の原文と、原因・直し方が分かります。

エラー文は curl の版で少し変わります。8.23.0 と、Ubuntu 24.04 の 8.5.0 で同じ操作をしたときの文を並べます。

番号 8.23.0 のエラー文 8.5.0 のエラー文
(3) URL rejected: Bad query URL rejected: Malformed input to a URL function
(7) Failed to connect to localhost:1 after 0 ms: Could not connect to server Failed to connect to localhost port 1 after 0 ms: Couldn't connect to server
(23) client returned ERROR on write of 105 bytes Failure writing output to destination
(35) TLS connect error: error:0A00010B:SSL routines::wrong version number OpenSSL/3.0.13: error:0A00010B:SSL routines::wrong version number
(60) SSL certificate OpenSSL verify result: unable to get local issuer certificate (20) SSL certificate problem: unable to get local issuer certificate

curl: (6) Could not resolve host

$ curl -sS http://no-such-host.invalid/
curl: (6) Could not resolve host: no-such-host.invalid

ホスト名から IP アドレスを引けていません。URL のつづり、DNS の設定、社内ネットワークならプロキシの要否を確かめます。DNS を通さずに試すには、--resolve ホスト:ポート:IP で IP を指定します。

$ curl -s --resolve api.example.test:40280:127.0.0.1 http://api.example.test:40280/echo -w '\n%{remote_ip}\n'
{"method": "GET", "path": "/echo", ...}
127.0.0.1

curl: (7) Failed to connect

$ curl -sS http://localhost:1/
curl: (7) Failed to connect to localhost:1 after 0 ms: Could not connect to server

名前解決はできたが、そのポートにつながりません。サーバーが起動していない、ポート番号の間違い、ファイアウォールが主な原因です。ポートの待ち受けは ss -ltn で確かめられます。

curl: (28) Operation timed out

$ curl -sS --max-time 2 http://localhost:40281/
curl: (28) Operation timed out after 2001 milliseconds with 0 bytes received

with 0 bytes received は、接続はできたが応答が1バイトも来なかったことを示します。-w の time_connect と time_starttransfer を見ると、接続で止まったのか、サーバーの処理で止まったのかを分けられます。

curl: (35) TLS connect error

$ curl -sS https://localhost:40280/
curl: (35) TLS connect error: error:0A00010B:SSL routines::wrong version number

$ curl -sS --tls-max 1.1 --cacert ca.pem https://localhost:40443/echo
curl: (35) TLS connect error: error:0A0000BF:SSL routines::no protocols available

1つ目は、HTTP で待ち受けているポートに https:// で接続したときのエラーです。URL の http と https、ポート番号を見直します。2つ目は、TLS の版が合わないときのエラーです。プロキシが通信を中継している環境でも (35) が出ることがあり、-v で接続先を確かめます。

curl: (60) SSL certificate problem

自作の CA で発行した証明書、自己署名の証明書、期限切れの証明書、IP アドレスでの接続で試しました。

状況 8.23.0 のエラー文の要点
信頼していない CA が発行 unable to get local issuer certificate (20)
自己署名の証明書 self-signed certificate (18)
期限切れ certificate has expired (10)
証明書の名前と URL が違う no alternative certificate subject name matches target IPv4 address '127.0.0.1'
$ curl -sS https://localhost:40443/echo
curl: (60) SSL certificate OpenSSL verify result: unable to get local issuer certificate (20)
More details here: https://curl.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the webpage mentioned above.

直し方は、信頼する CA 証明書を --cacert で渡すことです。 渡すと 200 が返り、検証の結果(ssl_verify_result)は 0 になりました。

$ curl -sS --cacert ca.pem -o /dev/null -w '%{http_code} ssl_verify_result=%{ssl_verify_result}\n' https://localhost:40443/echo
200 ssl_verify_result=0

$ curl -sS -k -o /dev/null -w '%{http_code} ssl_verify_result=%{ssl_verify_result}\n' https://localhost:40444/echo
200 ssl_verify_result=18

証明書のエラーを消すとき

やってはいけない-k で検証を省く。ssl_verify_result=18 のまま 200 が返り、相手が本物か確かめないので、途中で盗み見る攻撃を防げない
↔
こうする--cacert で社内 CA の証明書を渡す。ssl_verify_result=0 で通る。OS に登録済みなら --ca-native(8.2.0 以降)

-k は開発中の一時的な確認だけにし、スクリプトや CI に残さない

リダイレクトする URL に POST するとき

やってはいけない-L -X POST。302 の転送先に本文の無い POST が送られた
↔
こうする-X POST を書かずに -L -d、または --follow -X POST(8.16.0 以降)

-d・--json・-F を付ければ POST になる

証明書の中身(期限・発行者・名前)の確かめ方は、関連記事「opensslコマンドの使い方|目的別一覧と実行結果・エラー対処【3系】」で扱っています。

その他のエラー

エラー文 原因 直し方
curl: (1) Protocol "htps" not supported URL のスキームのつづり違い http://・https:// を見直す
curl: option --no-such-option: is unknown(終了コード 2) オプションの書き間違い・版が古くて無い curl --help all と curl -V で確かめる
curl: The file 'nofile.pem' provided to --cacert does not exist(終了コード 2) --cacert のファイルが無い パスを確かめる
curl: (52) Empty reply from server サーバーが何も返さず接続を切った サーバーのログ、HTTP と HTTPS の取り違えを確かめる
curl: (47) Maximum (50) redirects followed リダイレクトがループしている -w '%{redirect_url}' で転送先を追う
curl: (23) client returned ERROR on write of 105 bytes 保存先のディレクトリが無い --create-dirs を付ける
curl: Failed to open nofile.json(終了コード 26) -d @ファイル のファイルが無い パスを確かめる

Windowsでcurlコマンドを使う(curl.exe と PowerShell の curl の違い)

この節では、Windows で curl と打ったときに何が動くのかと、引用符でつまずかない書き方が分かります。

curl 公式の説明では、Windows 10(Insider ビルド 17063 以降)と Windows 11 には標準で curl が入っています。Microsoft Learn には、upstream の curl から作られているため、Linux や macOS と同じオプション・同じ動作で使えると書かれています。つまずくのは、Windows PowerShell 5.1 で curl が別のコマンドになることです。

シェル curl と打ったときに動くもの 本物の curl を使うには
コマンドプロンプト(cmd) curl.exe そのまま curl
Windows PowerShell 5.1 Invoke-WebRequest の別名 curl.exe と書く
PowerShell 7 以降 curl.exe(別名は無い) そのまま curl

Microsoft Learn によると、Windows PowerShell 5.1 の Invoke-WebRequest には iwr・curl・wget の3つの別名があり、PowerShell 7 以降は iwr だけです。5.1 で本物の curl を使うには、curl.exe と拡張子まで書くか、Remove-Item Alias:curl で別名を消します。

curl.exe -sS --fail-with-body https://api.example.com/users

PowerShell 7.6.4 で Get-Command curl を実行すると、CommandType は Application(外部のプログラム)でした。Invoke-WebRequest の別名は iwr だけでした。

PowerShell で JSON の引用符が消える

PowerShell 7.3 で、外部のコマンドへの引数の渡し方が変わりました($PSNativeCommandArgumentPassing)。about_Parsing によると、選べる値は Legacy・Standard・Windows で、既定は Windows では Windows、Windows 以外では Standard です。PowerShell 7.6.4 で値を切り替えて同じコマンドを送り、サーバーが受け取った本文を比べました。

curl -s --json '{"name":"yamada"}' "http://localhost:40280/echo"
設定 サーバーが受け取った本文
Windows(Windows での既定) {"name":"yamada"}
Standard(Windows 以外での既定) {"name":"yamada"}
Legacy(7.3 より前の渡し方) {name:yamada}(" が消えた)
Legacy で '{\"name\":\"yamada\"}' と書いた {"name":"yamada"}
--json "@user.json"(ファイルから) {"name":"yamada"}

Windows PowerShell 5.1 と同じ Legacy の渡し方では、JSON の " が消え、壊れた JSON が送られました。 どの環境でも同じ結果になるのは、JSON をファイルに書いて --json "@user.json" で送る方法です。

コマンドプロンプト(cmd)での書き方

cmd では、シングルクォートは引用符として扱われません。Microsoft の引数の解析規則では、" で囲んだ中の \" が " になります。

curl -H "Content-Type: application/json" -d "{\"name\":\"yamada\"}" https://api.example.com/users
  • 行を折り返すときは、\ ではなく ^ を使う(PowerShell では `)
  • 本文を捨てるときは -o /dev/null ではなく -o nul(8.16.0 以降は --out-null。マニュアルの例)
  • バッチファイルの中では、-w "%{http_code}" の % を %% と2つ重ねる(マニュアルの --write-out の注意)

Invoke-WebRequest・Invoke-RestMethod との対応

PowerShell の機能で同じことをするときの対応です。PowerShell 7.6.4 で動かしました。

curl PowerShell
curl URL Invoke-WebRequest -Uri URL
curl --json '{...}' URL Invoke-RestMethod -Method Post -Uri URL -ContentType 'application/json' -Body $json
curl -H 'X: 1' URL Invoke-WebRequest -Uri URL -Headers @{X='1'}
curl -o file URL Invoke-WebRequest -Uri URL -OutFile file
404 でも終了コード 0 404 で例外(HttpResponseException)。-SkipHttpErrorCheck で例外にしない

curl.exe の終了コードは、PowerShell では $LASTEXITCODE で取れます。curl -s -f で 404 を取ったとき、LASTEXITCODE=22 でした。PowerShell の他のコマンドは、関連記事「PowerShellコマンド一覧|用途別50選とbash対応表・実行例付き」で扱っています。

Windows 同梱の curl の注意

curl 公式の説明では、Windows 同梱の curl は TLS に Schannel を使い、HTTP/2・HTTP/3・brotli・zstd・SCP・SFTP などが含まれていません。公式ページに載っている curl -V の例は 8.13.0 で、curl 公式の版より遅れて更新されます。新しい機能が要るときは、curl 公式サイトの Windows 版を使う方法があります。

wgetとcurlの違い

この節では、wget・curl・wcurl のどれを選ぶかが分かります。

curl の FAQ には「curl is not a Wget clone.」とあり、curl は1回ずつの転送を対象にした道具だと書かれています。同じテスト用サーバーに向けて、GNU Wget 1.21.4 と curl 8.23.0 を動かしました。

項目 curl wget
何もしないときの出力先 画面(標準出力) ファイルに保存
リダイレクト -L を付けたときだけたどる 既定でたどる
再試行 既定では無し(--retry) 既定で 20 回(ドキュメント)
404 のときの終了コード 0(-f で 22) 8
接続できないときの終了コード 7 4
名前解決できないときの終了コード 6 4
証明書を検証できないとき 60 5
フォルダーごと再帰的に取る できない -r でできる
メソッド・ヘッダーの指定 自由に組み立てられる 一部(--method・--header など)
$ curl -s -o /dev/null -w '%{http_code}\n' http://localhost:40280/redirect/2
302
$ wget -q -O - http://localhost:40280/redirect/2
{"method": "GET", "path": "/echo", "headers": {"user-agent": "Wget/1.21.4", ...}, "body": ""}

wcurl:curl でファイルを1つ取るための小さな道具

curl 8.23.0 のソースには、ファイルのダウンロード用の小さなシェルスクリプト「wcurl」が入っています(8.23.0 の変更履歴では v2026.10.12 を取り込み)。--dry-run で、実際に渡す curl のオプションが見えます。

$ wcurl --version
2026.10.12
$ wcurl --dry-run http://localhost:40280/files/report.txt
curl
--fail
--globoff
--location
--proto-default
https
--remote-time
--retry
5
--no-clobber
--output
report.txt
--url
http://localhost:40280/files/report.txt

「失敗を検知・リダイレクトをたどる・5回再試行・上書きしない」という、ダウンロードで付けたいオプションがまとめて付きます。

curl が向いている

API にメソッド・ヘッダー・本文を指定して送る

ステータスコードや応答時間だけを取り出す

TLS・リダイレクトの中身を -v で調べる

FTP・SFTP・SMTP など HTTP 以外も扱う

wget・wcurl が向いている

サイトやディレクトリを再帰的にまとめて取る(wget -r)

不安定な回線で、何度もやり直しながら大きなファイルを取る

オプションを考えずにファイルを1つ保存する(wcurl)

迷ったときの判断表

状況 選ぶもの
API を1回送って結果を見る curl(--json・-H)
送った中身・TLS を調べる curl -v・--trace-ascii
ファイルを1つ確実に保存する wcurl URL か curl -fLO --retry 5
サイト・フォルダーを丸ごと取る wget -r
PowerShell の中で結果をオブジェクトとして使う Invoke-RestMethod
同じリクエストを何度も送る curl -K 設定ファイル

wget の使い方は、関連記事「wgetコマンドの使い方|保存先・再帰・リトライとcurlの違い」で扱っています。

ブラウザの通信をcurlで再現する(Copy as cURL)

この節では、ブラウザが送ったリクエストを、そのまま curl のコマンドにする方法が分かります。

Chrome の開発者ツールの公式ドキュメントでは、Network パネルのリクエストを curl のコマンドとしてコピーできます。

1

開発者ツールの Network を開く

開発者ツールを開いて Network パネルを選び、確かめたいリクエストが Requests の表に並んだ状態にする。

Network

2

リクエストを右クリックする

Requests の表の Name 列で、対象のリクエストを右クリックする。

右クリック

3

Copy as cURL を選ぶ

Copy にカーソルを合わせ、Copy as cURL を選ぶ。同じメニューに Copy as PowerShell・Copy as fetch もある。

Copy

4

端末に貼って動かす

貼り付けて実行し、必要なら -v を足して、ブラウザと同じ結果になるかを確かめる。

-v

コピーしたコマンドには、Cookie やトークンなどログインの情報が入っています。 チャットや資料に貼るときは、その部分を伏せます。

よくある質問

Q. curlとは何ですか? A. URL を指定して、HTTP・HTTPS・FTP などでサーバーとデータを送受信するコマンドです。curl URL で GET を送り、返ってきた本文を画面に出します。「curlとは」の節で、やり取りの図と最初の1行を載せています。

Q. curlコマンドとは何に使うものですか? A. API の動作確認、ファイルのダウンロード、サーバーの疎通や応答時間の確認、通信の調査(-v)によく使われます。「curlでできること」の節にまとめています。

Q. curl の読み方は? A. 「カール」です。curl の FAQ では、k の音で始め、girl・earl と同じ韻で読むと説明しています。

Q. curl のオプション一覧を表示するには? A. curl --help all で全オプションを表示します。curl 8.23.0 では 274 個でした。curl --help http でカテゴリ、curl --help -i で1つのオプションの説明が出ます。目的から引く表は「curlのオプション一覧」の節にあります。

Q. curl コマンドのオプションでよく使うものは? A. -X(メソッド)、-H(ヘッダー)、-d・--json(本文)、-o・-O(保存)、-i・-v(ヘッダー・詳細)、-s(進捗を消す)、-L(リダイレクト)、-w(ステータスや時間)、-f(失敗を検知)です。

Q. curl の使い方の基本は? A. curl [オプション] URL の形です。まず curl URL で中身を見て、ヘッダーが要れば -i、送る中身を決めるなら -X・-H・--json を足します。「curlでAPIを確認する」の節に実行結果があります。

Q. Windows で curl コマンドは使えますか? A. Windows 10・11 には curl.exe が入っています。Windows PowerShell 5.1 では curl が Invoke-WebRequest の別名なので、curl.exe と書きます。JSON は --json "@ファイル" で送ると引用符で困りません。

Q. curl -v の見方は? A. * は curl からの説明、> は送ったヘッダー、< は受け取ったヘッダー、} { は送った・受け取った本文です。「curl -v の読み方」の節で1行ずつ読んでいます。

Q. curl -i とは何ですか? A. レスポンスヘッダーを本文の前に出すオプションです。長い名前は --show-headers(8.10.0 より前は --include)です。大文字の -I は HEAD リクエストでヘッダーだけを出します。

Q. curl -LO(curl -lo)の意味は? A. -L(リダイレクトをたどる)と -O(URL のファイル名で保存する)を並べた形です。小文字の -l は FTP の --list-only なので、ダウンロードには大文字の -LO を使います。

Q. -X POST は必要ですか? A. -d・--json・-F を付けると POST になるので、-X POST は無くても POST です。-L と一緒に -X POST を書くと、302 の転送先にも本文の無い POST が送られました。

Q. curl -k は使ってよいですか? A. -k は証明書の検証を省くので、相手が本物かを確かめません。社内 CA なら --cacert、OS に登録済みの CA なら --ca-native で検証したまま通せます。

Q. wget と curl の違いは? A. wget は既定でファイルに保存し、リダイレクトをたどり、再帰的なダウンロードができます。curl は既定で画面に出し、メソッドやヘッダーを細かく指定でき、API の確認に向いています。

Q. プロキシを経由したい A. -x http://proxy.example.com:8080 で指定するか、環境変数 HTTPS_PROXY・HTTP_PROXY を設定します。プロキシを使わないホストは --noproxy か NO_PROXY で指定します。

まとめ

  • curl は URL を使ってサーバーとデータを送受信するコマンド。curl URL で GET を送り、本文を画面に出す
  • まず curl -V で版と Features を確かめる(最新は 8.23.0、Ubuntu 24.04 は 8.5.0)
  • 通信の中身は -v で見る。* 説明、> 送信、< 受信
  • オプションは curl --help all(8.23.0 で 274 個)。目的から引くなら本文の早見表
  • JSON は --json、認証は -u・--oauth2-bearer、Cookie は -c と -b
  • ステータスは -s -o /dev/null -w '%{http_code}\n'、応答時間は time_*
  • 404・500 でも終了コードは 0。スクリプトでは -sS --fail-with-body と --max-time
  • エラーは番号で切り分ける:(6) 名前解決、(7) 接続、(28) 時間切れ、(35) TLS、(60) 証明書
  • Windows PowerShell 5.1 では curl.exe と書き、JSON はファイルから送る
  • まとめて取るなら wget、ファイル1つなら wcurl、API を確かめるなら curl

参考・出典

確認日はいずれも 2026年10月24日です。

  • curl - Changes(変更履歴):https://curl.se/changes.html
  • curl man page(オプションと EXIT CODES):https://curl.se/docs/manpage.html
  • curl - Frequently Asked Questions:https://curl.se/docs/faq.html
  • curl - History:https://curl.se/docs/history.html
  • curl - SSL CA Certificates:https://curl.se/docs/sslcerts.html
  • curl - Microsoft's curl(Windows 同梱の curl):https://curl.se/windows/microsoft.html
  • everything curl - Install(macOS・Linux):https://everything.curl.dev/install/index.html
  • Microsoft Learn - curl on Windows:https://learn.microsoft.com/en-us/windows/curl/
  • Windows Command Line - Tar and Curl Come to Windows!:https://devblogs.microsoft.com/commandline/tar-and-curl-come-to-windows/
  • Microsoft Learn - Invoke-WebRequest(Windows PowerShell 5.1):https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-webrequest?view=powershell-5.1
  • Microsoft Learn - Invoke-WebRequest(PowerShell 7.5):https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-webrequest?view=powershell-7.5
  • Microsoft Learn - about_Parsing($PSNativeCommandArgumentPassing):https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_parsing
  • Microsoft Learn - Parsing C command-line arguments:https://learn.microsoft.com/en-us/cpp/c-language/parsing-c-command-line-arguments
  • Chrome DevTools - Network features reference:https://developer.chrome.com/docs/devtools/network/reference
  • GNU Wget Manual - Exit Status:https://www.gnu.org/software/wget/manual/html_node/Exit-Status.html

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「curlとは?curlコマンドの使い方とオプション一覧|Windows・エラー対処」

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?