🎯 カスタマイズ可能で検出回避型のクラウドブラウザ。自社開発のChromiumを搭載し、ウェブクローラーAIエージェント向けに設計されています。👉今すぐ試す
ブログに戻ります

cURLを使ってJSONを送信する方法:-d、--json、および一般的な間違いに関する完全ガイド

Sophia Martinez
Sophia Martinez

Specialist in Anti-Bot Strategies

02-Jun-2026

主要なポイント:

  • cURLでJSONを送信することは、1つのことではなく2つのことです。 リクエストにJSONボディを添付し、Content-Type: application/jsonヘッダーを介してサーバーにそれがJSONであることを伝えます。ヘッダーを省略すると、多くのAPIはボディを拒否したり、誤って解析します。
  • -d/--dataはペイロードを運び、ヘッダーはあなたの責任です。 クラシックなパターンは curl -X POST -H "Content-Type: application/json" -d '{...}' URL です。-dは単体ではJSONヘッダーを設定しません。
  • --jsonは現代のショートカットです。 curl 7.82.0に追加された --json '{...}'は、ボディを送信し、Content-Type: application/jsonおよびAccept: application/jsonの両方を一つのフラグで設定します。
  • シェルのクオーテーションは多くの人が苦労するところです。 シェルが内部のダブルクオーテーションを食べないようにJSONをシングルクオーテーションで囲みます;Windowsのcmdではルールが異なり、ペイロードファイルの方が安全です。
  • @fileはディスクからボディを読み込みますが、正しいデータフラグを選んでください。 -d @body.jsonは改行を削除しますが、--data-binary @body.jsonおよび--json @body.jsonはファイルをバイト単位で送信します。
  • 同じリクエスト形状が実際のAPIを駆動します。 ホスティングされたScrapeless MCPエンドポイントへのJSON-RPC呼び出しは、JSONボディと認証ヘッダーを持つPOSTに過ぎません — このガイドが教える正確なパターンです。
  • 無料で開始できます。 新しいScrapelessアカウントには、無料のScraping Browserランタイムと住宅プロキシアクセスが含まれています — Scrapelessでサインアップしてください。

イントロダクション:すべてのAPI統合が始まるリクエスト

ほとんどすべての現代のWeb APIはJSONを話します。あなたはJSONボディで認証し、JSONボディでジョブを提出し、JSONボディでMCPサーバー上のツールを呼び出します。これらのいずれかがスクリプトやSDKの内部で実行される前に、通常は端末の単一の curl コマンドとして始まります — エンドポイントがドキュメント通りに動作するかを確認する最も早い方法です。

問題なのは、「curlでJSONを送信する」ということが、混同しやすい2つの別々の要件を隠していることです。一つは、リクエストボディとしてJSONテキストを添付することです。もう一つは、Content-Typeヘッダーを介してボディがJSONであることを宣言し、サーバーが正しく解析できるようにすることです。ボディは正しくてもヘッダーを忘れると、厳格なAPIは400を返したり、静かに何も読み込まなかったりします。シェルでJSONを間違って引用すると、curlは元々有効なJSONでなかった歪んだ文字列を送信します。

このガイドでは、「curlでJSONを送信する」という意味を正確に定義し、それを行う2つのフラグファミリー(-dとヘッダー、および新しい--json)を紹介し、パブリックエコーエンドポイントに対して実行できる成功した例を示し、混乱を招くエラーメッセージを生じさせる間違いを catalogします。最後には、同じリクエスト形状を実際のJSON API — ホスティングされたScrapeless MCPエンドポイント — への呼び出しにマッピングし、そのパターンが端末から本番環境に直接運ばれることを示します。関連する背景については、aiohttpを使った非同期HTTPスクレイピングのガイドや、SSLプロキシとはについての解説をご覧ください。


「cURLでJSONを送信する」とは

cURL(libcurlを使用したコマンドラインツール)は、HTTPやその他多くのプロトコルを介してデータを転送します。「cURLでJSONを送信する」とは、リクエストボディがJSONドキュメントであり、Content-Typeヘッダーapplication/jsonに設定されたHTTPリクエストを発行することを意味します。

これら2つの要素は独立しており、どちらも重要です:

  • ボディは生のJSONテキストです — 例えば {"product":"laptop","max_price":1200}。curlはこれらのバイトをそのままリクエストエンティティとして送ります。
  • Content-Typeヘッダーはサーバーにこれらのバイトをどのように解釈するかを伝えます。これがなければ、curlの-dのデフォルトはapplication/x-www-form-urlencodedで、HTMLフォーム送信に使われる形式です。このヘッダーを見るJSON APIはリクエストを拒否するか、ボディをフォームフィールドとして解析しようとして失敗します。

したがって、正しいJSONリクエストは常にJSONボディとJSONコンテンツタイプをペアにします。唯一の疑問は、そのペアリングを生成するためにどのcurlフラグを使用するかであり、それが従来の -d プラスヘッダーアプローチと、以下で説明される単一フラグ --json ショートカットとの違いです。

用語に関する簡単な注意点: -d--data の短縮形で、 -H--header の短縮形です。これらは互換性があります;このガイドでは例に短縮形を使用し、役立つ場合には長縮形を名前にします。


方法1:-d / --dataとContent-Typeヘッダー

これは移植性があり、どこでも動作するアプローチで、APIドキュメントで最もよく見られます。ボディは-dで提供し、ヘッダーは-Hで提供します:

bash Copy
curl -X POST https://httpbin.org/post \
  -H "Content-Type: application/json" \
  -d '{"product":"laptop","max_price":1200}'

ここで3つのことが起こっています:

  • -X POSTはHTTPメソッドを設定します。厳密には、-dはすでにPOSTを暗示しているため、ここでの-X POSTは省略可能です。しかし、明示的に書くことで意図が明確になり、ボディフラグを別の方法で変更した場合にデフォルトがGETになることを防ぐために必要です。
  • -H "Content-Type: application/json"はボディフォーマットを宣言します。
  • -d '{...}'はJSONを添付します。シングルクォートはシェルがJSON内のダブルクォートを解釈するのを防ぎます。

これをhttpbin.org/postに対して実行すると、受信した内容をそのまま返してくれるパブリックエンドポイントがあり、返ってくるのは以下の通りです:

json Copy
{
  "data": "{\"product\":\"laptop\",\"max_price\":1200}",
  "headers": {
    "Accept": "*/*",
    "Content-Type": "application/json",
    "Host": "httpbin.org",
    "User-Agent": "curl/8.18.0"
  },
  "json": {
    "max_price": 1200,
    "product": "laptop"
  },
  "origin": "203.0.113.10",
  "url": "https://httpbin.org/post"
}
// フィールド値は説明的なサンプルです。構造はhttpbinが返すものです。

成功の鍵となる信号はjsonオブジェクトです:httpbinは、ボディが有効なJSONとして解析され、かつContent-Typeapplication/jsonである場合にのみこれを populatesします。Acceptヘッダーは*/*であり — curlのデフォルトです — -dAcceptには影響を与えません。なお、-d自体はJSONヘッダーを設定しません:上記のContent-Typeは、あなたが-H行を追加したために存在しているだけです。その行を削除すると、httpbinはContent-Type: application/x-www-form-urlencodedを報告し、空のjsonフィールドとなります。


方法2: --jsonフラグ(curl 7.82.0以降)

--jsonフラグはcurl 7.82.0で登場しました(2022年初頭にリリース)。これにより、一般的なケースを1つのオプションに統合できます。curl --versionでバージョンを確認してください。7.82.0以降が報告される場合、--jsonが利用可能です。

bash Copy
curl -X POST https://httpbin.org/post \
  --json '{"product":"laptop","max_price":1200}'

単一の--jsonは同時に3つの仕事をします。指定されたテキストをリクエストボディとして送信し、次の2つのヘッダーを設定します:

  • Content-Type: application/json
  • Accept: application/json

この2番目のヘッダーが方法1との実用的な違いです:--jsonはまた、サーバーに対してJSONを受け取りたいと伝え、一部のAPIがレスポンスフォーマットを選択するために使用します。httpbinを介してリクエストをエコーすることで確認できます:

json Copy
{
  "data": "{\"product\":\"laptop\",\"max_price\":1200}",
  "headers": {
    "Accept": "application/json",
    "Content-Type": "application/json",
    "Host": "httpbin.org",
    "User-Agent": "curl/8.18.0"
  },
  "json": {
    "max_price": 1200,
    "product": "laptop"
  },
  "origin": "203.0.113.10",
  "url": "https://httpbin.org/post"
}
// AcceptもContent-Typeも今やapplication/jsonです。

--jsonを複数回渡すことができ、curlはフラグメントを1つのボディに結合します — 部品からペイロードを組み立てるのに便利です。--jsonが設定するヘッダーの1つをオーバーライドする必要がある場合(たとえば、異なるAccept)、その後に明示的な-Hを追加してください。この後のヘッダーが勝ちます。

それぞれの方法をいつ使用すべきか?新しい作業には現在のcurlで--jsonを使用します。古いcurlビルドをサポートする必要がある場合や、どのヘッダーが存在するかを完全に制御したい場合、または従うドキュメントがそのように書かれている場合は、-d-Hを使用します。

挙動 -d '{...}' -d '{...}' -H "Content-Type: application/json" --json '{...}'
JSONをボディとして送信する はい はい はい
デフォルトのHTTPメソッド POST POST POST
Content-Type: application/jsonを設定する しない(form-urlencodedがデフォルト) はい(設定した) はい(自動)
Accept: application/jsonを設定する しない しない はい(自動)
最小curlバージョン いずれか いずれか 7.82.0

無料プランでAPIキーを取得する: Scrapeless


@を使用してJSONファイルを送信する

インラインJSONはフィールドが数個を超えると扱いが難しく、大きなペイロードはファイルに保存すべきです。-d--jsonの両方がボディをパスから読み込むための@プレフィックスを受け入れます。次のようなbody.jsonがあるとします:

json Copy
{
  "product": "laptop",
  "max_price": 1200
}

どちらのフラグでも送信できます:

bash Copy
# クラシック:データフラグ + 明示的なヘッダー
curl -X POST https://httpbin.org/post \
  -H "Content-Type: application/json" \
  -d @body.json

# モダン:1つのフラグ
curl -X POST https://httpbin.org/post \
  --json @body.json

ファイルの読み取り方には微妙だが重要な違いがあります。-d @body.jsonはファイルから新しい行とキャリッジリターンを取り除きます — これはフォームデータ用に設計されたためです。サーバーに到達するボディは{ "product": "laptop", "max_price": 1200}になります:これは依然として有効なJSONです(トークン間のホワイトスペースは許可されています)が、ディスク上の内容と一致しなくなります。

2つのフラグはファイルを正確に維持します:

bash Copy
# --data-binaryはすべてのバイト(新しい行を含む)を保持します
curl -X POST https://httpbin.org/post \
  -H "Content-Type: application/json" \
  --data-binary @body.json

# --json @fileもファイルをそのまま送信します
plaintext Copy
curl -X POST https://httpbin.org/post \
  --json @body.json

通常のJSONの場合、改行を省いたバージョンでも解析できますので、-d @fileは通常うまくいきます。しかし、ペイロードがファイルのバイト単位で一致する必要がある場合(署名が正確なバイトに対して計算される、またはファイルに意味のある埋め込まれた改行を含む文字列値がある場合)は、--data-binary @fileまたは--json @fileを使用してください。

他のプログラムがJSONを生成する際に便利な@-を使ってスタンダード入力からボディをパイプすることもできます:

bash Copy
generate_payload | curl -X POST https://httpbin.org/post --json @-

よくある間違い(およびその回避方法)

これらは、5秒のcurlをデバッグセッションに変えてしまう失敗です。

1. Content-Type ヘッダーを忘れる

最も一般的なものです。プレーンな-dでヘッダーがない場合、curlは Content-Type: application/x-www-form-urlencodedを送信します。JSON APIは、そのリクエストを4xxで拒否するか、空のボディを読み取ります。修正方法: -H "Content-Type: application/json"を追加するか、あなたの代わりに自動的に設定する--jsonに切り替えてください。

2. JSONを壊すシェルの引用

JSONはダブルクォートを使用しますが、ほとんどのシェルも展開のためにダブルクォートを使用します。ペイロードをダブルクォートで囲むことで、curlがそれを見る前にシェルがその部分を削除または展開してしまいます:

bash Copy
# bash/zshでは間違い:シェルが内側のダブルクォートを消費する
curl -X POST https://httpbin.org/post --json "{"product":"laptop"}"

# 正しい:ペイロード全体をシングルクォートで囲む
curl -X POST https://httpbin.org/post --json '{"product":"laptop"}'

修正方法: bash/zshではJSONドキュメント全体をシングルクォートで囲みます。値がリテラルなシングルクォートを含む必要がある場合は、それをエスケープするか、ペイロードをファイルに移動して@fileを使用します。これによりシェルの引用の問題を完全に回避できます。

3. Windows cmdの引用が異なる

Windowsのcmd.exeはシングルクォートを引用文字として扱わないため、シングルクォートのトリックが失敗します。内側のダブルクォートをバックスラッシュでエスケープするか、より信頼性の高い方法としてJSONをファイルに格納して@body.jsonで送信してください。PowerShellには独自の引用ルールがあり、curlのエイリアスは歴史的にInvoke-WebRequestを指していました。curl.exeを明示的に呼び出し、サプライズを避けるために@file形式を好んで使用してください。修正方法: Windowsでは、@body.jsonを使ってペイロードファイルを使用します。

4. -Gによってボディがクエリ文字列に変わる

-G/--getはcurlに-dデータをURLのクエリパラメータとして追加するように指示し、ボディを送信するのではなくなります。これはGETリクエストには適したツールですが、JSONをPOSTしようとする際にそれをオンにしておくと、ペイロードがURLに静かに移動し、ボディが空になります。修正方法: -GをJSONボディと組み合わせない、-X POSTを使用してください(または-d/--jsonをPOSTにデフォルトで設定させてください)。

5. 無効なJSONを送信する

curlはボディのバリデーションを行わず、与えられたテキストをそのまま送信します。トレーリングカンマ、引用されていないキー、またはシングルクォートの文字列は、サーバーによって拒否され、しばしば不透明なパースエラーが発生します。修正方法: 送信前にペイロードをバリデートしてください。JSONパーサーでの迅速なローカルチェックでほとんどの問題をキャッチできます:

bash Copy
# curlが実行される前に不正なJSONで速やかに失敗
echo '{"product":"laptop","max_price":1200}' | python -c "import sys, json; json.load(sys.stdin); print('valid')"

6. APIのコンテンツ交渉時にAcceptを忘れる

いくつかのAPIはJSONを要求しない限りXMLやHTMLを返します。-dではContent-Typeのみ設定され、Acceptは設定されないため、リクエストがJSONであっても応答がJSONでない可能性があります。修正方法: -H "Accept: application/json"を追加するか、または--jsonを使用して、あなたのためにAcceptを設定してください。


実際の例:JSON APIの呼び出し

まとめて、これが本物のJSON API呼び出しの形です。ホスティングされたScrapeless MCPエンドポイントはHTTPでJSON-RPCを話します。これは、あなたが構築しているリクエスト、すなわちJSONボディと認証ヘッダーを持つPOSTです。APIキーは環境変数から読み取るので、シェルの履歴に決して表示されることはありません:

bash Copy
# ボディはinit.jsonにあり、キーはコマンドラインではなく環境から来ます
curl -X POST "https://api.scrapeless.com/mcp" \
  -H "x-api-token: ${SCRAPELESS_API_KEY}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  --data-binary @init.json

init.jsonにはJSON-RPCハンドシェイクが含まれています:

json Copy
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2024-11-05",
    "capabilities": {},
    "clientInfo": { "name": "curl-demo", "version": "1.0" }
  }
}

このガイドのすべてのコンセプトが含まれています:JSONボディ(ここではファイルから、--data-binaryでそのまま送信)、JSONとしてマークするContent-Type: application/jsonヘッダー、返却される形式を指定するAcceptヘッダー、そして認証情報を持つ認証ヘッダー。ホストされたエンドポイントは、google_searchscrape_htmlscrape_markdownbrowser_*オートメーションセットなど、おおよそ二十数のツールを公開しており、各ツールは同じPOST JSONボディパターンで呼び出されますが、methodparamsだけが異なります。詳細はScrapelessのドキュメントで確認できます。

もちろん、エンドポイントに生のcurlで話し続ける必要はありませんが、最初にcurlでエンドポイントを証明してから、検証されたリクエストをお好みの言語に移植することが、最も時間を節約するワークフローです。MCPサーバーの完全なツールカタログと実装されたエージェントプロンプトについては、5 Scrapeless MCPユースケースを参照してください。


Scrapelessの位置づけ

curlコマンドが動作するようになったら、次のステップは通常、大規模に実行することです — 多くのリクエストを、JavaScriptでコンテンツをレンダリングするサイトや、オートメーションされたトラフィックを相手に行います。ここで、あなたが学んだリクエストの形が管理されたインフラストラクチャと出会います。

Scrapelessは、検出対策クラウドブラウザであるScrapeless Scraping Browserと、195か国以上の住宅プロキシを提供しており、ホストされたMCPエンドポイント、SDK、CLIを通じてアクセスできます。このブラウザは、JavaScriptが重いページをクラウド側でレンダリングし、フィンガープリンツを管理するため、curlでプロトタイプしたクリーンなJSONリクエストが、チャレンジページの代わりに構造化されたデータを返します。トランスポートの詳細 — 住宅の出口を固定すること、セッションを持続させること — はあなたのために処理されます;あなたの側は、シンプルな「JSONボディをPOSTし、JSONを読み戻す」というループのままです。

Scraping Browser製品を探索し、価格ページでプランを確認し、ドキュメントでAPIとMCPリファレンスを見つけてください。


結論

curlでJSONを送信するには、2つの要件を一緒に満たす必要があります:リクエストボディとしてJSONを添付し、Content-TypeヘッダーでそれをJSONとして宣言すること。クラシックな方法は-d '{...}'-H "Content-Type: application/json"を追加することです;モダンな1フラグの方法は--json '{...}'で、これによりContent-TypeAcceptがcurl 7.82.0以上で自動的に設定されます。大きなまたは署名されたペイロードをファイルに移し、--data-binary @fileまたは--json @fileで送信してすべてのバイトを保持し、bashでインラインJSONをシングルクォートで囲んでシェルクォーテーションを克服し、Windowsでペイロードファイルを探します。同じリクエスト — ボディとコンテンツタイプと認証ヘッダー — は、実際のJSON API(Scrapeless MCPエンドポイントのような)を呼び出すときの正確な形であり、これがターミナルで動作するcurlが生産環境にクリーンに移植される理由です。関連する読み物として、aiohttpによる非同期HTTPスクレイピングSSLプロキシとは何かを参照してください。


FAQ

Q: curlでJSONを送るための最も簡単な方法は何ですか?

現在のcurl(7.82.0以上)では、curl --json '{"key":"value"}' URLが最も短い正しい形式です — 本体を送信し、Content-TypeAcceptの両方のヘッダーをapplication/jsonに設定します。古いcurlでは、curl -X POST -H "Content-Type: application/json" -d '{"key":"value"}' URLを使用します。

Q: 送信したのにJSON APIがボディが欠如または無効だと言います。なぜですか?

通常、2つの原因があります。1つは、Content-Type: application/jsonヘッダーなしで-dを送信したため、サーバーがそれをフォームデータとして読み取った場合です — ヘッダーを追加するか、--jsonを使用します。もう1つは、シェルがJSONを二重引用符でラップしたために、JSONが壊れた場合です;ペイロードをシングルクォートで囲むか、ファイルに移動して@fileで送信します。

Q: -d--data-binary--jsonの違いは何ですか?

-d--data)はボディを送信し、@fileの場合は改行を削除します;独自にJSONヘッダーを設定しません。--data-binaryは、与えられた通りにボディを送信し、改行をそのまま保持します。--jsonはボディをそのまま送信し、Content-TypeAcceptapplication/jsonに設定します;curl 7.82.0以上が必要です。

Q: インラインテキストの代わりにJSONファイルを送信するにはどうすればいいですか?

パスを@で始めます:curl --json @body.json URL、またはcurl -H "Content-Type: application/json" --data-binary @body.json URL。ファイルのバイトが正確に一致する必要がある場合、-d @fileよりも--json @fileまたは--data-binary @fileを優先してください;なぜなら-d @fileは改行を削除するからです。

Q: Windows上でcurlを使ってJSONを送信するにはどうすればいいですか?

cmd.exeはシングルクォートを尊重しないため、最も信頼できる簡単な方法はJSONをファイルに保存し、@body.jsonで送信することです。もしインラインで送信する必要がある場合は、すべての内側の二重引用符をバックスラッシュでエスケープします。PowerShellでは、curl.exeを明示的に呼び出して、Invoke-WebRequestエイリアスに遭遇しないようにし、やはり@file形式を優先してください。
Q: --jsonを使用する場合、Content-Typeヘッダーを設定する必要がありますか?

いいえ。--jsonは自動的にContent-Type: application/jsonAccept: application/jsonを設定します。異なるAcceptのように、これらのいずれかを上書きするために明示的なヘッダーを追加する必要がある場合、その場合は--jsonの後に-Hを置いて優先されるようにしてください。


AI搭載のデータパイプラインを構築する準備はできましたか?

私たちのコミュニティに参加して、無料プランを請求し、JSON駆動のデータ収集パイプラインを構築している開発者とつながりましょう: Discord · Telegram

Scrapeless にサインアップして、無料のスクレイピングブラウザのランタイムと住宅用プロキシへのアクセスを取得し、プロトタイプが作成したcurlリクエストを本番データパイプラインに変えましょう。


Scrapelessでは、適用される法律、規制、およびWebサイトのプライバシーポリシーを厳密に遵守しながら、公開されているデータのみにアクセスします。 このブログのコンテンツは、デモンストレーションのみを目的としており、違法または侵害の活動は含まれません。 このブログまたはサードパーティのリンクからの情報の使用に対するすべての責任を保証せず、放棄します。 スクレイピング活動に従事する前に、法律顧問に相談し、ターゲットウェブサイトの利用規約を確認するか、必要な許可を取得してください。

最も人気のある記事

カタログ