Python RequestsでPOST JSONを送信する方法 (2026年版)
PythonのrequestsライブラリでJSONデータを送信するための完全ガイド
Hyperealで構築を始めよう
Kling、Flux、Sora、Veoなどに単一のAPIでアクセス。無料クレジットで開始、数百万規模まで拡張可能。
クレジットカード不要 • 10万人以上の開発者 • エンタープライズ対応
Python Requests で JSON の POST リクエストを送信する方法 (2026年版)
Python の requests ライブラリは、Python エコシステムで最も人気のある HTTP ライブラリであり、JSON データを含む POST リクエストの送信は最も一般的なユースケースの一つです。REST API の呼び出し、ウェブフックへのデータ送信、またはサードパーティ製サービスとの連携など、どのような場合でもリクエストを正しく構成する方法を知っておく必要があります。
このガイドでは、基本から認証、エラーハンドリング、リトライ、非同期リクエストなどの高度なパターンまでを網羅します。
基本:JSON POST リクエストの送信
方法 1: `json` パラメータを使用する(推奨)
JSON データを送信するための、最もシンプルで正しい方法です。
import requests
url = "https://api.example.com/v1/users"
data = {
"name": "Jane Doe",
"email": "jane@example.com",
"role": "developer"
}
response = requests.post(url, json=data)
print(response.status_code) # 200
print(response.json()) # JSON レスポンスをパース
json パラメータを使用すると、requests は自動的に以下の処理を行います:
- 辞書型を JSON 文字列にシリアライズする
Content-Typeヘッダーをapplication/jsonに設定する- データを UTF-8 としてエンコードする
方法 2: `data` パラメータと手動シリアライズを使用する
シリアライズをより細かく制御する必要がある場合に使用します。
import requests
import json
url = "https://api.example.com/v1/users"
data = {
"name": "Jane Doe",
"email": "jane@example.com"
}
response = requests.post(
url,
data=json.dumps(data),
headers={"Content-Type": "application/json"}
)
この方法を使用するタイミング: カスタムの JSON シリアライズが必要な場合(例:特定の日付フォーマットや 10 進数の処理など)に限ります。それ以外のすべてのケースでは、json=data を使用してください。
重要な違い: `json` vs `data`
| パラメータ | シリアライズ | Content-Type | ユースケース |
|---|---|---|---|
json=data |
自動 (json.dumps) |
自動設定される | 標準的な JSON API |
data=json.dumps(data) |
手動 | 手動設定が必要 | カスタムシリアライズ |
data=data |
フォームエンコード | application/x-www-form-urlencoded |
HTML フォーム、レガシー API |
よくある間違いは、JSON API に対して(json.dumps を使わずに)data=data を使用することです。これは JSON ではなくフォームエンコードされたデータを送信するため、サーバー側で拒否される可能性が高いです。
ヘッダーの追加
標準的なヘッダー
headers = {
"Content-Type": "application/json", # json= パラメータ使用時は自動設定されます
"Accept": "application/json",
"User-Agent": "MyApp/1.0"
}
response = requests.post(url, json=data, headers=headers)
json=data を使用する場合、Content-Type を手動で設定する必要はありません。requests ライブラリが処理します。ただし、Accept や User-Agent を設定することは良いプラクティスです。
API キー認証
headers = {
"X-API-Key": "your-api-key-here",
"Accept": "application/json"
}
response = requests.post(
"https://api.example.com/v1/generate",
json={"prompt": "A sunset over mountains", "model": "flux"},
headers=headers
)
Bearer トークン認証
headers = {
"Authorization": "Bearer eyJhbGciOiJIUzI1NiIs...",
"Accept": "application/json"
}
response = requests.post(url, json=data, headers=headers)
ベーシック認証 (Basic Authentication)
from requests.auth import HTTPBasicAuth
response = requests.post(
url,
json=data,
auth=HTTPBasicAuth("username", "password")
)
# 簡略版
response = requests.post(url, json=data, auth=("username", "password"))
レスポンスの処理
JSON レスポンスのパース
response = requests.post(url, json=data)
# リクエストが成功したか確認
if response.ok: # ステータスコード 200-299 の場合に True
result = response.json()
print(result)
else:
print(f"Error: {response.status_code}")
print(response.text)
レスポンスの詳細検査
response = requests.post(url, json=data)
print(f"Status: {response.status_code}")
print(f"Headers: {dict(response.headers)}")
print(f"Content-Type: {response.headers.get('Content-Type')}")
print(f"Response time: {response.elapsed.total_seconds()}s")
print(f"Body: {response.text}")
# Content-Type が JSON の場合のみパースする
if "application/json" in response.headers.get("Content-Type", ""):
print(f"JSON: {response.json()}")
ステータスコード別の処理
response = requests.post(url, json=data)
match response.status_code:
case 200 | 201:
result = response.json()
print(f"Success: {result}")
case 400:
print(f"Bad request: {response.json().get('error', 'Unknown')}")
case 401:
print("Unauthorized: check your API key")
case 403:
print("Forbidden: insufficient permissions")
case 404:
print("Endpoint not found: check your URL")
case 429:
retry_after = response.headers.get("Retry-After", "60")
print(f"Rate limited: retry after {retry_after} seconds")
case 500:
print("Server error: try again later")
case _:
print(f"Unexpected status: {response.status_code}")
エラーハンドリングとリトライ
基本的なエラーハンドリング
import requests
from requests.exceptions import (
ConnectionError,
Timeout,
HTTPError,
RequestException
)
try:
response = requests.post(
url,
json=data,
timeout=30 # 必ずタイムアウトを設定してください
)
response.raise_for_status() # 4xx/5xx の場合に HTTPError を発生させる
result = response.json()
except ConnectionError:
print("Failed to connect to server")
except Timeout:
print("Request timed out")
except HTTPError as e:
print(f"HTTP error: {e.response.status_code}")
except RequestException as e:
print(f"Request failed: {e}")
指数バックオフを用いたリトライ
import requests
import time
def post_with_retry(url, json_data, headers=None, max_retries=3, base_delay=1):
"""指数バックオフを用いて POST リクエストをリトライ送信する。"""
for attempt in range(max_retries):
try:
response = requests.post(
url,
json=json_data,
headers=headers,
timeout=30
)
# 429 以外のクライアントエラーはリトライしない
if 400 <= response.status_code < 500 and response.status_code != 429:
response.raise_for_status()
# レート制限時のリトライ
if response.status_code == 429:
retry_after = int(response.headers.get("Retry-After", base_delay * (2 ** attempt)))
print(f"Rate limited. Waiting {retry_after}s...")
time.sleep(retry_after)
continue
# サーバーエラー時のリトライ
if response.status_code >= 500:
raise requests.exceptions.HTTPError(response=response)
return response
except (requests.exceptions.ConnectionError, requests.exceptions.Timeout) as e:
if attempt == max_retries - 1:
raise
delay = base_delay * (2 ** attempt)
print(f"Attempt {attempt + 1} failed: {e}. Retrying in {delay}s...")
time.sleep(delay)
raise Exception(f"All {max_retries} attempts failed")
# 使用例
response = post_with_retry(
"https://api.example.com/v1/data",
json_data={"key": "value"},
headers={"X-API-Key": "your-key"}
)
`requests.Session` による接続の再利用
同じサーバーに対して複数のリクエストを送信する場合、Session を使用して TCP 接続を再利用します。
import requests
session = requests.Session()
session.headers.update({
"X-API-Key": "your-api-key",
"Accept": "application/json"
})
# このセッションを通じたすべてのリクエストは、同じヘッダーと接続プールを共有します
response1 = session.post("https://api.example.com/v1/users", json={"name": "Alice"})
response2 = session.post("https://api.example.com/v1/users", json={"name": "Bob"})
response3 = session.post("https://api.example.com/v1/users", json={"name": "Charlie"})
session.close()
セッションは、クッキー管理、接続プール、および Keep-Alive も自動的に処理します。
高度なパターン
ネストされた JSON の送信
data = {
"user": {
"name": "Jane Doe",
"address": {
"street": "123 Main St",
"city": "San Francisco",
"state": "CA"
}
},
"preferences": {
"notifications": True,
"theme": "dark",
"languages": ["en", "es", "fr"]
}
}
response = requests.post(url, json=data)
JSON とファイルアップロードの同時送信
1つのリクエスト内で json= と files= を同時に使用することはできません。両方を必要とする API の場合は、JSON をフォームフィールドとしてエンコードします。
import json
files = {
"image": ("photo.jpg", open("photo.jpg", "rb"), "image/jpeg"),
"metadata": (None, json.dumps({"title": "My Photo", "tags": ["nature"]}), "application/json")
}
response = requests.post(url, files=files, headers={"X-API-Key": "key"})
大規模な JSON レスポンスのストリーミング
巨大なレスポンスを返す API の場合:
response = requests.post(url, json=data, stream=True)
# レスポンスをチャンクごとに処理
for chunk in response.iter_content(chunk_size=8192):
process_chunk(chunk)
httpx による非同期リクエスト
非同期サポート(async/await)が必要なアプリケーションでは、httpx(requests 互換の API を持ちます)を使用します。
import httpx
import asyncio
async def post_json_async():
async with httpx.AsyncClient() as client:
response = await client.post(
"https://api.example.com/v1/data",
json={"key": "value"},
headers={"X-API-Key": "your-key"},
timeout=30.0
)
return response.json()
# 実行
result = asyncio.run(post_json_async())
asyncio による並列リクエスト
import httpx
import asyncio
async def send_batch(items):
async with httpx.AsyncClient() as client:
tasks = [
client.post(
"https://api.example.com/v1/process",
json={"item": item},
headers={"X-API-Key": "your-key"}
)
for item in items
]
responses = await asyncio.gather(*tasks)
return [r.json() for r in responses]
items = ["item1", "item2", "item3", "item4", "item5"]
results = asyncio.run(send_batch(items))
よくある間違いと解決策
| 間違い | 問題点 | 解決策 |
|---|---|---|
json=data ではなく data=data を使用 |
JSON ではなくフォームエンコードで送信される | json=data を使用する |
timeout パラメータの欠如 |
リクエストが永久にハングする可能性がある | 常に timeout=30 などを設定する |
response.raise_for_status() を呼ばない |
4xx/5xx エラーがサイレントに失敗する | エラーチェックを追加する |
| API キーをハードコードする | セキュリティリスク | 環境変数を使用する |
| Session を使用しない | 複数リクエスト時にパフォーマンスが低下する | requests.Session() を使用する |
| レスポンスヘッダーの Content-Type を無視する | 非 JSON レスポンス時に .json() でクラッシュする |
実行前に Content-Type を確認する |
クイックリファレンス
import requests
# シンプルな POST
response = requests.post("https://api.example.com/data", json={"key": "value"})
# ヘッダー付き
response = requests.post(url, json=data, headers={"X-API-Key": "key"})
# タイムアウト付き
response = requests.post(url, json=data, timeout=30)
# 認証付き
response = requests.post(url, json=data, auth=("user", "pass"))
# レスポンスの確認
response.status_code # 200
response.json() # パースされた JSON
response.text # 生のテキスト
response.headers # レスポンスヘッダー
response.ok # 200-299 の場合に True
response.raise_for_status() # 4xx/5xx の場合に例外を発生
結論
Python の requests を使った JSON POST リクエストの送信は、パターンさえ分かれば非常に簡単です。自動シリアライズには json=data を使い、常にタイムアウトを設定し、本番コードではリトライロジックを実装し、同じサーバーへの複数リクエストには Session を活用しましょう。
Python の HTTP スキルを試すための実践的な API をお探しなら、Hypereal AI が AI による画像生成、ビデオ作成、音声合成のための REST API を提供しています。これらのエンドポイントは、API キー認証を用いた標準的な JSON POST リクエストを受け付けており、このガイドで学んだパターンの完璧な実例となります。
