curl/wget入門 - コマンドラインでのHTTP通信

curl/wget入門 - コマンドラインでのHTTP通信

この記事で学べること

  • curlwget役割の違い が腑に落ちる
  • ファイルダウンロード・ヘッダー確認・API アクセスの 基本コマンド が書ける
  • 初心者がハマりやすい 「保存されない」「リダイレクトされない」「文字化け」 の原因が分かる
  • API レスポンスの確認や HTTP ステータスの読み方が コピペで動かせる ようになる

結論(先に覚える型)

  • 単発のファイルダウンロード → wget URL
  • API 叩く・ヘッダー確認・POST → curl URL
  • リダイレクトを追従したい → curl -L URL
  • ダウンロードが途中で切れた → wget -c URL

前提(対象環境)

  • OS:Ubuntu / 一般的な Linux
  • curl は標準搭載が多い。wgetsudo apt install wget で導入
  • 対象は HTTP / HTTPS(curl は ftp / sftp / smtp 等も対応)

1. curl と wget の違い:まず役割を分ける

リナ: 先輩、curl と wget ってどっちも「URL からデータを取ってくる」コマンドですよね? どっちを使えばいいのか毎回迷います...
ライニー先輩: いい質問。実は 設計思想が違う から、使い分けの基準があるんだ。一言で言うと、wget は ダウンローダー、curl は 多機能 HTTP クライアント
リナ: ダウンローダーと、クライアント...?
ライニー先輩: wget は「URL を渡したらファイルを保存する」のがデフォルト動作。curl は「URL を叩いてレスポンスを画面に出す」のがデフォルト。これが全ての違いに繋がる。

ざっくり比較

項目 curl wget
デフォルト動作 標準出力に表示 ファイルとして保存
HTTP メソッド GET/POST/PUT/DELETE 等 基本 GET のみ
リダイレクト追従 -L を付ける必要あり 自動で追従
再帰ダウンロード 苦手 得意(-r
レジューム -C - で対応 -c で対応
用途 API 叩く・デバッグ・POST サイト丸ごとミラー・DL

迷ったら:API・ヘッダー・POST が絡むなら curl、ファイル落とすだけなら wget。

2. curl の基本:まず画面に出す

2-1. URL を叩いて結果を画面に出す

$ curl https://example.com
<!doctype html>
<html>
<head>
    <title>Example Domain</title>
...
リナ: えっ、HTML が全部画面に流れてきました。
ライニー先輩: それが curl のデフォルト動作。標準出力(画面)に丸ごと吐く。ファイルにしたければ -o(名前指定)か -O(URL のファイル名を使う)を付ける。

2-2. 名前を指定して保存 -o

$ curl -o page.html https://example.com

-ooutput(出力)の頭文字。小文字の o はファイル名を引数で指定する。

2-3. URL のファイル名で保存 -O

$ curl -O https://example.com/sample.tar.gz

大文字の O は URL の末尾のファイル名(この例なら sample.tar.gz)でそのまま保存。

-o-O を間違えると悲しい結末

  • -O を付ける URL は 末尾がファイル名であること が前提
  • curl -O https://example.com/(末尾スラッシュ)はファイル名が決まらず失敗する
  • 迷ったら -o 名前 で明示する方が安全

2-4. ダウンロード進捗を見たい

$ curl -O --progress-bar https://example.com/big.iso

--progress-bar でシンプルな進捗バーが出る。長時間ダウンロードで安心。

3. 初心者の最大の罠:リダイレクト -L

リナ: 先輩、https://github.com/torvalds/linux を curl で取ってみたんですけど、中身が変なんです...
ライニー先輩: ああ、それ典型的なハマりポイント。GitHub やショート URL は HTTP の リダイレクト が挟まることが多い。curl はデフォルトで リダイレクトを追わない から、リダイレクト先のページじゃなくて「ここに移動しました」という案内ページが返ってくる。
リナ: 追わないの? wget は追ってくれましたよ?
ライニー先輩: そう。そこが両者の違い。curl は 明示的に -L を付ける とリダイレクトを追従するようになる。

3-1. リダイレクトを追従する -L

# NG: リダイレクトされた案内が返るだけ
$ curl https://github.com/torvalds/linux

# OK: 最終ページの内容を取得
$ curl -L https://github.com/torvalds/linux

-LLocation(HTTP の Location ヘッダー)の頭文字。

型として覚える

  • 外部サイトを curl で叩くときは 常に -L を付ける と事故が減る
  • ファイルダウンロードでも -L 必須のケースが多い(GitHub Releases 等)
# 安全な定番形
$ curl -LO https://github.com/some/repo/releases/download/v1.0/binary.tar.gz

「リンク先は生きてる?」「リダイレクト先はどこ?」を 本文をダウンロードせずに 確認できる。

$ curl -I https://example.com
HTTP/2 200
content-type: text/html; charset=UTF-8
content-length: 1256
date: Sun, 26 May 2026 09:00:00 GMT
server: ECS
リナ: なるほど、HTTP/2 200 は「成功」ですよね?
ライニー先輩: その通り。最初の数字が HTTP ステータスコード。これだけ覚えれば実務の 9 割は対応できる。

HTTP ステータス 早見表

コード 意味 状況
2xx 成功 200 OK204 No Content
3xx リダイレクト 301(恒久)、302(一時)
4xx クライアント側 404(無い)、401/403(権限)
5xx サーバー側 500(バグ)、503(過負荷)

4-1. リダイレクト先を辿る

$ curl -ILs https://bit.ly/3xxxxx | grep -i location

-L でリダイレクト追従、-s で進捗非表示、-I でヘッダーのみ。location: 行で遷移先 URL が分かる。

5. POST と JSON:API を叩く

リナ: REST API を curl で叩きたいんですけど、JSON ってどう送ればいいんですか?
ライニー先輩: API テストは curl の真骨頂。-X で HTTP メソッド、-H でヘッダー、-d でボディを指定する。JSON を送るなら 3 点セット を覚えるだけ。

5-1. GET(クエリパラメータ付き)

$ curl "https://api.example.com/users?id=42"

URL に ? 以降を含めるときは 必ずクォート する(シェルが & を解釈しないように)。

5-2. POST で JSON を送る

$ curl -X POST https://api.example.com/users \
    -H "Content-Type: application/json" \
    -d '{"name":"lina","role":"beginner"}'

3 点セットの意味

  • -X POST:HTTP メソッド指定(-d を使うと省略可だが明示が安全)
  • -H "Content-Type: application/json":「JSON 送ります」宣言
  • -d '...':送る本体(JSON)。シングルクォート推奨(中の " をエスケープ不要にするため)

5-3. Bearer トークン認証

$ curl https://api.example.com/me \
    -H "Authorization: Bearer YOUR_TOKEN_HERE"

トークンを履歴に残さない

# NG: シェル履歴・ps に丸見え
$ curl -H "Authorization: Bearer abc123..." ...

# OK: 環境変数経由
$ export API_TOKEN=abc123...
$ curl -H "Authorization: Bearer $API_TOKEN" ...

historyps でトークンが見えると事故。環境変数か ~/.netrc を使う。

5-4. 基本認証(Basic 認証)

$ curl -u username:password https://example.com/private

-uuser:pass を渡す。HTTPS 必須。

6. wget の本領:堅実なダウンロード

6-1. 基本:ファイルとして保存

$ wget https://example.com/sample.tar.gz
リナ: wget は何もオプション付けなくてもファイルになるんですね、楽。
ライニー先輩: そう、wget は 保存がデフォルト。curl と違ってリダイレクトも自動追従するから、シンプルな DL なら wget の方が事故が少ない。

6-2. 名前を変えて保存 -O

$ wget -O custom.tar.gz https://example.com/sample.tar.gz

curl と wget で -O の意味が逆

  • curl の -O:URL のファイル名で保存
  • wget の -Oファイル名を指定 して保存(curl の -o 相当)

両方使う人はここで必ず一度ハマる。

6-3. 中断したダウンロードを再開 -c

$ wget -c https://example.com/big.iso

-ccontinue。回線が切れて途中までしか落ちてないファイルの 続きから ダウンロードする。

6-4. リトライ・タイムアウト

$ wget --tries=5 --timeout=30 https://example.com/file.zip

不安定な回線でも諦めず再試行する設定。

7. 再帰ダウンロード wget -r(注意して使う)

$ wget -r -l 2 -np https://example.com/docs/
  • -r:再帰的にリンクをたどる
  • -l 2:階層を 2 階層までに制限
  • -np:親ディレクトリに登らない

8. 文字化け・改行コードの罠

リナ: 取ってきた HTML が &lt; とか変な記号だらけで読めません。
ライニー先輩: ブラウザは自動でデコードしてくれるけど、curl/wget は そのまま 渡す。日本語ページの文字化けは、サイトの文字コードを意識して iconv で変換するか、jq などの専用ツールを通すと解決する。
リナ: 改行コードも気になります...
ライニー先輩: Windows サーバから取ってきたファイルは \r\n(CRLF)になることがある。Linux で扱うなら dos2unixtr -d '\r' で除去するのが定番。
# Shift_JIS のページを UTF-8 に変換しながら保存
$ curl -s https://example.com/sjis.html | iconv -f SHIFT_JIS -t UTF-8 > page.html

# CRLF を LF に変換
$ curl -s https://windows-server.example/data.csv | tr -d '\r' > data.csv

9. よくある初心者のつまずき

9-1. curl URL で何も保存されない

原因:curl のデフォルトは「画面に出す」。保存したいなら -O-o

$ curl -O https://example.com/file.zip
$ curl -o my.zip https://example.com/file.zip

9-2. リダイレクト先の中身が取れない

原因-L を忘れている。

$ curl -L https://github.com/...

9-3. クエリ文字列が bash: command not found になる

原因& がシェルのバックグラウンド実行記号として解釈された。

# NG
$ curl https://api.example.com/search?q=linux&page=2

# OK
$ curl "https://api.example.com/search?q=linux&page=2"

9-4. SSL 証明書エラーで止まる

原因:自己署名証明書、期限切れ、社内 CA など。

# 検証あり(推奨)
$ curl https://internal.example.com

# 検証スキップ(緊急回避のみ。本番禁止)
$ curl -k https://internal.example.com

-k検証スキップ。中間者攻撃のリスクが上がる。本番運用では証明書を正しく整える。

9-5. プロキシ環境で繋がらない

$ export http_proxy=http://proxy.example.com:8080
$ export https_proxy=http://proxy.example.com:8080
$ curl https://example.com

社内環境では http_proxy / https_proxy を設定する。

10. ミニ課題:手を動かして確かめよう

リナ: 知識は入りました! ターミナルで試したいです。
ライニー先輩: 3 問用意したよ。https://httpbin.org は HTTP リクエスト確認用の練習サイト。安心して叩いていい。

課題 1https://httpbin.org/get の HTTP ステータスコードと content-type を確認しよう。

ヒントを見る

ヘッダーだけ取るオプションがあった。

解答例
$ curl -I https://httpbin.org/get
HTTP/2 200
date: ...
content-type: application/json
...

課題 2https://httpbin.org/post に JSON {"hello":"world"} を POST しよう。

ヒントを見る

-X POST / -H / -d の 3 点セット。

解答例
$ curl -X POST https://httpbin.org/post \
    -H "Content-Type: application/json" \
    -d '{"hello":"world"}'

レスポンス内の "json": {"hello": "world"} が確認できれば成功。

課題 3https://httpbin.org/redirect/3 のリダイレクト先を辿って、最終ページを取得しよう。

ヒントを見る

リダイレクトを追従するオプションが必要。

解答例
$ curl -L https://httpbin.org/redirect/3

3 回リダイレクトされた末の /get のレスポンスが返る。

11. コピペ用テンプレート

curl テンプレ

# 画面に表示(デバッグ)
curl URL

# 保存(URL のファイル名で)
curl -O URL

# 保存(名前指定)
curl -o name URL

# リダイレクト追従しつつ保存(GitHub Releases 等)
curl -LO URL

# ヘッダーだけ確認
curl -I URL

# ステータスコードだけ取得
curl -s -o /dev/null -w "%{http_code}\n" URL

# JSON を POST
curl -X POST URL \
    -H "Content-Type: application/json" \
    -d '{"key":"value"}'

# Bearer トークン
curl URL -H "Authorization: Bearer $API_TOKEN"

# 基本認証
curl -u user:pass URL

# 進捗バー付き
curl -O --progress-bar URL

wget テンプレ

# 基本ダウンロード
wget URL

# 名前を変えて保存
wget -O custom.name URL

# 中断したファイルの続き
wget -c URL

# リトライ・タイムアウト指定
wget --tries=5 --timeout=30 URL

# 静かにダウンロード(ログ最小)
wget -q URL

# 再帰ダウンロード(マナー注意)
wget -r -l 2 -np --wait=2 https://example.com/docs/

まとめ:次に読む