技術資料

PowerShellでcurlを使う:REST APIのGET・JSON POSTとエラーの確認

作成日:2026.11.03

WindowsのPowerShellからcurlでREST APIを試す方法を紹介します。GETのクエリ指定、JSONファイルのPOST、Bearer認証ヘッダーの付け方に加え、レスポンスの保存やHTTPステータス・終了コードによるエラーの切り分けを解説します。

REST APIを使うとき、いきなりアプリケーションへ組み込むより、まずはリクエストだけを送って確認したいことがあります。URLや送信データが違うのか、PHPなどの実装に問題があるのかを分けて調べたいときにも便利です。

今回は、WindowsのPowerShellからコマンドライン版curlを使い、GETとJSON POSTを試してみます。レスポンスの本文だけでなく、HTTPステータスとcurlの終了コードも確認します。

PowerShellから使うcurlを確認する

curlは、URLを指定してデータを送受信するコマンドラインツールです。PHPのcURL拡張とは別に実行するプログラムなので、PHPのコードを書かずにHTTPリクエストを送れます。

PowerShellでは、コマンドの別名と外部プログラムを区別します。例えばWindows PowerShell 5.1では、curlがInvoke-WebRequestの別名になっています。この記事では、外部プログラムを呼び出すことが分かるようにcurl.exeと書きます。

$PSVersionTable.PSVersion
Get-Command curl -All
Get-Command curl.exe
curl.exe --version

今回確認した環境は、WindowsのOSビルド10.0.26300、PowerShell 7.6.9、curl 8.21.0です。curlのTLSバックエンドはSchannelでした。

以下で使う--jsonはcurl 7.82.0以降のオプションです。古いcurlでは使えないため、手元のバージョンも確認してください。

GETでAPIへリクエストを送る

ここからは、商品を扱う説明用APIを例にします。以下のサンプルコード内のhttps://api.example.comは実行可能なサンプルAPIではありません。接続先、パス、パラメーターは、利用するAPIの仕様へ置き換えてください。

POSTはデータを登録する場合があるので、まずは自分で操作してよいテスト環境を使いましょう。後ほどファイルも保存するため、空の作業用フォルダーで試してください。

$baseUrl = 'https://api.example.com'

例えば、商品の一覧を取得するGET /productsなら、次の形です。

curl.exe --silent --show-error --connect-timeout 5 --max-time 15 "$baseUrl/products"

データ送信用のオプションなどを付けなければ、HTTPでは基本的にGETになります。返された本文は画面へ出力されますが、curlが自動でJSONを整形するわけではありません。

指定意味
--silent進捗やエラーメッセージなどの表示を抑える。本文は出力する
--show-error--silentを使っていてもエラーメッセージを表示する
--connect-timeout 5接続を確立するまでの時間を最大5秒にする
--max-time 15今回の転送全体を最大15秒にする

進捗だけ消したつもりでエラーまで見えなくならないよう、ここでは--silentと--show-errorをセットで指定しています。

クエリパラメーターとヘッダーを付ける

検索語や件数を指定する例です。--getと--data-urlencodeを組み合わせると、値をURLエンコードしてクエリへ追加できます。

curl.exe --silent --show-error `
    --connect-timeout 5 --max-time 15 `
    --get `
    --data-urlencode 'q=入門 PHP' `
    --data-urlencode 'limit=2' `
    --header 'Accept: application/json' `
    "$baseUrl/products"

この例では、qに「入門 PHP」、limitに「2」を渡します。--getを外すと、このデータ指定はPOSTになるので注意してください。Acceptは、レスポンスとしてJSONを受け取りたいという指定です。実際の応答はAPIの仕様によります。

PowerShellでコマンドを複数行に分けるときは、上の例のように行末へバッククォート`を置けます。バッククォートの後ろに空白を入れると、行の継続になりません。実行できないときは、いったん1行に戻してみると切り分けやすいです。

本文・ヘッダー・HTTPステータスを分けて確認する

本文だけでは、成功したのか、APIのエラーメッセージなのか判断しにくい場合があります。本文とレスポンスヘッダーを別ファイルへ保存し、画面にはHTTPステータスを表示してみます。

curl.exe --silent --show-error `
    --connect-timeout 5 --max-time 15 `
    --dump-header '.\response-headers.txt' `
    --output '.\response.json' `
    --write-out 'HTTP=%{http_code}\n' `
    "$baseUrl/products"
$curlExitCode = $LASTEXITCODE
"curl exit=$curlExitCode"

--dump-headerは受信ヘッダー、--outputは本文の保存先です。--write-outは転送後に情報を出力する指定で、%{http_code}がHTTPステータス、\nが改行になります。

$LASTEXITCODEには最後に実行した外部プログラムの終了コードが入ります。別のプログラムを動かす前に、curlの実行直後で保存します。

Get-Content -LiteralPath '.\response-headers.txt'
Get-Content -LiteralPath '.\response.json' -Raw -Encoding utf8

ここではJSONの応答を想定したファイル名にしていますが、保存しただけでは内容がJSONかどうかは検証されません。通信に失敗した場合は、保存ファイルが今回の完全な応答とは限らないので、先に終了コードを確認してください。同名の保存ファイルは上書きされます。

JSONファイルをPOSTする

JSONをコマンドへ直接書くと、JSONのダブルクォートとシェルの引用符が重なります。まずはファイルへ保存して送る方が、送信内容を確認しやすいかと思います。

例えば、nameとpriceを受け取るAPIなら、次のようにJSONを作れます。PowerShell 7系で、BOMなしのUTF-8として保存します。

$requestBody = @{
    name = 'テスト商品'
    price = 1200
}
$requestBody | ConvertTo-Json | Set-Content -LiteralPath '.\request.json' -Encoding utf8NoBOM

このファイルを、商品登録のPOST /productsへ送ります。

curl.exe --silent --show-error `
    --connect-timeout 5 --max-time 15 `
    --json '@request.json' `
    --output '.\post-response.json' `
    --write-out 'HTTP=%{http_code}\n' `
    "$baseUrl/products"
$curlExitCode = $LASTEXITCODE
"curl exit=$curlExitCode"
Get-Content -LiteralPath '.\post-response.json' -Raw -Encoding utf8

@request.jsonの@は、curlへファイルから読み込むよう指示する記号です。PowerShell側の解釈と混ざらないよう、引数全体を引用符で囲んでいます。空白を含むパスでも、'@.\request files\request.json'のように全体を囲みます。

--jsonは、ファイルなどのデータをPOSTし、Content-Type: application/jsonとAccept: application/jsonを指定するためのオプションです。この例では-X POSTを追加する必要はありません。ただし、JSON構文の検証は行わないので、ファイルを手で編集した場合などは内容も確認してください。

Content-Typeは送る本文の形式、Acceptは受け取りたい形式です。名前は似た場面で登場しますが、役割は別です。

Bearerトークンを付ける場合

Bearer認証を使うAPIでは、Authorizationヘッダーを追加します。次の例は、利用するAPIのテスト用トークンが環境変数API_TOKENへ設定されている前提です。

if ([string]::IsNullOrWhiteSpace($env:API_TOKEN)) {
    throw 'API_TOKENが設定されていません。'
}
curl.exe --silent --show-error `
    --connect-timeout 5 --max-time 15 `
    --header "Authorization: Bearer $env:API_TOKEN" `
    --json '@request.json' `
    "$baseUrl/products"

実トークンをコマンドへ直接書くと、履歴に残る可能性があります。ただ、環境変数を使っても、展開された値がプロセスの引数へ渡る点は変わりません。共有端末での扱いや、詳細ログ・画面・レスポンスを共有するときの漏えいにも注意してください。今回の検証ではダミー文字列だけを送っています。

HTTPエラーとcurlの失敗を分ける

HTTP 404や500が返っても、通常のcurlは終了コード0になることがあります。サーバーから応答を受け取れたことと、APIの処理が成功したことは別だからです。

HTTP 400以上をcurlの失敗としても扱い、エラー本文を残したい場合は、--fail-with-bodyを付けます。例えば、存在しない商品へアクセスして404を返すAPIなら、次のように確認できます。

curl.exe --silent --show-error `
    --connect-timeout 5 --max-time 15 `
    --fail-with-body `
    --output '.\error-response.json' `
    --write-out 'HTTP=%{http_code}\n' `
    "$baseUrl/products/999999"
$curlExitCode = $LASTEXITCODE
"curl exit=$curlExitCode"

ローカルのテスト用APIで404を返した場合、画面にはHTTPステータス404と終了コード22が表示され、本文はerror-response.jsonへ保存されました。curlのエラーメッセージは標準エラーへ出ます。

--failでもHTTPエラーを失敗扱いにできますが、エラー本文の出力は抑えられます。APIが返した理由を調べたい場合は、本文を残す--fail-with-bodyが便利です。こちらはcurl 7.76.0以降で使えます。

ローカルで確認した条件HTTPステータスcurlの終了コード
通常のGET2000
JSON POST2010
HTTPエラー、--fail-with-bodyなし400/404/5000
同じHTTPエラー、--fail-with-bodyあり400/404/50022
応答前にタイムアウト00028
待ち受けのないローカルポートへ接続0007

表の000はサーバーが返したHTTPステータスではなく、HTTP応答コードを取得できなかった場合の表示です。また、curlの終了コード0でも、API独自の成功条件は本文や仕様を見て判断します。

タイムアウトも同じように、実行直後の終了コードで確認できます。

curl.exe --silent --show-error `
    --connect-timeout 1 --max-time 1 `
    --output '.\timeout-response.txt' `
    --write-out 'HTTP=%{http_code}\n' `
    "$baseUrl/products"
$curlExitCode = $LASTEXITCODE
"curl exit=$curlExitCode"

このコマンドが必ずタイムアウトするわけではありません。検証では、ローカルサーバーが応答を返す前に2秒待つようにして、終了コード28を確認しました。特にPOSTのタイムアウトでは、サーバー側の登録処理は完了している場合もあるので、結果を確認せず繰り返し送らないようにしましょう。

接続できない場合は、URL、ネットワーク、プロキシ、証明書などをエラーメッセージから切り分けます。HTTPSの証明書エラーを消すために--insecure(-k)を付けるのは避け、原因を確認します。

なお、CLI版curlで成功しても、PHPのcURLが同じTLSバックエンドやCAを使っているとは限りません。PHP側の証明書エラーは、証明書検証とCAバンドルの設定を扱う記事も参考にしてください。

補足:Bashの例をPowerShellへ持ってくるとき

Bashで同じJSONファイルを送るなら、例えば次の形です。これはBash用の記法で、今回の実行検証の対象はPowerShell側です。

curl --silent --show-error \
    --connect-timeout 5 --max-time 15 \
    --json '@request.json' \
    'https://api.example.com/products'

Bashの行末の\を、そのままPowerShellの行継続には使えません。PowerShellではバッククォートを使うか、コマンドを1行にまとめます。変数の書き方や引用符の扱いも同一ではないため、Web上の例は「どのシェルで実行するものか」を確認しましょう。

今回のPowerShellの例は、URLをローカルのテスト用APIへ差し替えて確認しました。日本語を含むクエリ、JSONの内容、ヘッダーの受信と、表にあるHTTPエラー・タイムアウトを検証しています。実サービスの認証、HTTPS接続、プロキシ環境での動作は今回の検証には含めていません。

まずはGETで疎通を確認し、送信内容を増やしていくと、APIとのやり取りを追いやすくなります。リクエスト単体で確認できたら、PHPのcURLによる外部API連携など、アプリケーション側の実装へ進めばOKです。

参考資料

この記事を書いた人

※上が私です。

奈良市を拠点に、27年以上の経験を持つフリーランスWebエンジニア、阿部辰也です。

これまで、ECサイトのバックエンド開発や業務効率化システム、公共施設の予約システムなど、多彩なプロジェクトを手がけ、企業様や制作会社様のパートナーとして信頼を築いてまいりました。

【制作会社・企業様向けサポート】
  • 専任エンジニアのいない企業様に対するシステム面の不安を解消
  • 柔軟な契約形態や短納期での対応により、急なニーズにも迅速にサポート
  • システムの企画段階から運用まで、ワンストップでのサービスを提供

Webシステムの開発やサイト改善でお困りの際は、どうぞお気軽にご相談ください。小さな疑問から大規模プロジェクトまで、最適なご提案を心を込めてさせていただきます。

ぜひ、プロフィールやWeb制作会社様向け業務案内、一般企業様向け業務案内もご覧くださいね。

php -rの使い方:PowerShellでPHPを手軽に試す

2026.11.04

PHPファイルを作らずにコードを実行できる「php -r」の基本的な使い方を紹介します。PowerShellで変数や関数を試す例と、引用符による変数展開でエラーになる原因・対処法を説明し、Bashとの違いやPHPファイルへ切り出す目安も補足します。

PHP PowerShell

PHP cURLの証明書エラー:VERIFYPEERを無効にする危険性とCAバンドルの設定方法

2026.11.02

PHPのcURLで「unable to get local issuer certificate」が出たとき、CURLOPT_SSL_VERIFYPEERをfalseにする対処が危険な理由を解説します。証明書の信頼性検証とホスト名照合の違いを整理し、WindowsでのCAバンドルの取得、curl.cainfoの設定、反映確認までを紹介します。

cURL OpenSSL PHP

PowerShellコマンド入門:cmd.exe・Unix系コマンドとの対応と基本の使い方

2026.10.27

cmd.exe(DOSコマンド)やUnix系コマンドに慣れた人向けに、PowerShellの基本操作を対応表付きで解説します。cd・dir・grep・tailなどに相当する操作から、別名と外部コマンドの違い、圧縮・展開、オブジェクトを扱うパイプラインまで、具体例で紹介します。

PowerShell

PowerShell 7.6.6が起動しない:totalWidthエラーの原因と対処法

2026.10.21

PowerShell 7.6.6が起動直後にtotalWidthエラーで終了する問題について、更新通知を無効にして復旧した手順を紹介します。多言語メッセージの整形処理にある不具合と、更新・通知を戻す際の注意点も説明します。

PowerShell

阿部辰也へのお仕事の依頼・お問い合わせ

軽いご相談もお気軽にどうぞ!

個人情報の取り扱いについて *必須 プライバシーポリシーをご確認いただき、同意いただける場合は「同意する」にチェックをしてください。

keyboard_double_arrow_up
TOP