概要(requests.postは「サーバへデータを送る」ための最短ルート)
requests.postは、フォーム送信やJSONの投稿、ファイルアップロードなど「データをサーバへ渡す」場面で使います。重要なのは「ボディの作り方(form か JSON か)」「ヘッダーの指定」「タイムアウトと例外処理」「レスポンスの検証(ステータスと内容)」の4点です。まずは成功可否のチェックを型にし、用途に応じてボディの形式を正しく選べば、初心者でも安全にAPIとやり取りできます。
基本の使い方(ここが重要)
最短のPOSTと成功可否の確認
# pip install requests
import requests
url = "https://httpbin.org/post"
resp = requests.post(url, data={"name": "Taro", "age": "25"}, timeout=5)
print(resp.status_code) # 200なら成功
resp.raise_for_status() # 失敗(4xx/5xx)を例外にする
print(resp.text[:200]) # 応答の先頭だけ確認
Pythonstatus_codeでざっくり確認し、raise_for_statusで失敗を見落とさない型にします。timeoutは必ず付けて「待ちすぎ」を防ぎます。
JSONボディの投稿(APIの最頻パターン)
import requests
payload = {"user": "taro", "score": 88}
resp = requests.post("https://httpbin.org/post", json=payload, timeout=5)
resp.raise_for_status()
data = resp.json() # 応答がJSONなら辞書として受け取れる
print(data["json"]) # サーバ側が受け取ったJSONの確認
Pythonjson=… を使うと Content-Type: application/json が自動で付き、辞書をそのまま送れます。APIは基本的にこの形式が多いです。
フォーム(x-www-form-urlencoded)投稿
import requests
form = {"username": "taro", "password": "secret"}
resp = requests.post("https://httpbin.org/post", data=form, timeout=5)
resp.raise_for_status()
print(resp.json()["form"])
PythonWebフォームと同じ形式。ブラウザの通常のPOST送信に近い挙動になります。
ファイルアップロード(multipart/form-data)
単一ファイルを送る
import requests
with open("avatar.png", "rb") as f:
files = {"file": ("avatar.png", f, "image/png")}
resp = requests.post("https://httpbin.org/post", files=files, timeout=10)
resp.raise_for_status()
print(resp.json()["files"]) # サーバ側が受け取ったファイル
Pythonfiles=… を使うと自動で multipart/form-data になります。タプルで(ファイル名, ファイルオブジェクト, MIMEタイプ)を渡すと親切です。
複数ファイル・フォーム値の同時送信
import requests
data = {"user": "taro"}
files = [
("docs", ("spec.pdf", open("spec.pdf", "rb"), "application/pdf")),
("docs", ("plan.txt", open("plan.txt", "rb"), "text/plain")),
]
resp = requests.post("https://httpbin.org/post", data=data, files=files, timeout=20)
resp.raise_for_status()
print(resp.json()["form"], resp.json()["files"])
Python同じフィールド名で複数ファイルを送る場合はリストで渡します。ファイルを開いたら、可能ならwith文でクローズを忘れないようにします。
ヘッダー・認証・セッション
ヘッダー指定(認証や内容の宣言)
import requests
headers = {"Authorization": "Bearer YOUR_TOKEN", "Accept": "application/json"}
resp = requests.post("https://httpbin.org/post", json={"x": 1}, headers=headers, timeout=5)
resp.raise_for_status()
print(resp.json())
PythonAPIではAuthorizationやAcceptがよく使われます。json=を使うとContent-Typeは自動設定されるので、重複指定は不要です。
セッションで接続・クッキーを使い回す
import requests
with requests.Session() as s:
s.headers.update({"User-Agent": "MyClient/1.0"})
s.post("https://httpbin.org/cookies/set/user/taro")
r = s.post("https://httpbin.org/post", json={"hello": "world"}, timeout=5)
r.raise_for_status()
print(r.json())
PythonSessionは認証とクッキーを維持し、複数回リクエストを効率化します。毎回同じヘッダーを足す手間も減ります。
タイムアウト・エラー・再試行(事故を防ぐ型)
代表的な例外の捕捉
import requests
try:
r = requests.post("https://httpbin.org/status/500", json={"x": 1}, timeout=5)
r.raise_for_status()
except requests.Timeout:
print("タイムアウト")
except requests.ConnectionError:
print("接続エラー")
except requests.HTTPError as e:
print("HTTPエラー:", e)
except requests.RequestException as e:
print("その他のリクエスト例外:", e)
PythonまずはTimeoutとHTTPError、ConnectionErrorを押さえ、最後にRequestExceptionで取りこぼしを防ぐのが基本です。
安全な自動リトライ(サーバ一時不調に備える)
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
session = requests.Session()
retry = Retry(total=3, backoff_factor=0.5, status_forcelist=[500, 502, 503, 504])
adapter = HTTPAdapter(max_retries=retry)
session.mount("http://", adapter)
session.mount("https://", adapter)
resp = session.post("https://httpbin.org/status/503", json={"x": 1}, timeout=5)
print(resp.status_code)
PythonPOSTは「非冪等(同じリクエストを再送すると副作用が重複し得る)」なので、再試行は「サーバが処理していない可能性が高い失敗」に絞るのが安全です。API設計で「idempotency-key」を導入しているサービスでは再試行がより安全になります。
レスポンスの扱い(内容・文字コード・バイナリ)
JSON応答を辞書で扱う
import requests
r = requests.post("https://httpbin.org/post", json={"q": "tokyo"}, timeout=5)
r.raise_for_status()
print(r.json()) # dictやlistで扱える
Pythonjson()で辞書化すれば、そのままキーアクセスや後続処理に渡せます。JSON以外の応答では例外が出ることがあるため、Content-Typeを確認してから使うと安心です。
テキストと文字化け対策、バイナリ
import requests
r = requests.post("https://httpbin.org/html", timeout=5)
r.encoding = r.apparent_encoding # 推定文字コードで上書き
print(r.text[:100]) # テキストとして読む
rb = requests.post("https://httpbin.org/anything", data=b"\x00\x01\x02")
print(type(rb.content), len(rb.content)) # バイナリは content
Pythontextは文字列、contentはバイナリ。文字化けするならencodingを明示します。
実務の型(OS連携・大きな送信・検証)
応答をファイルへ保存(画像やPDF)
import requests
from pathlib import Path
out = Path("downloads/resp.json")
out.parent.mkdir(parents=True, exist_ok=True)
r = requests.post("https://httpbin.org/post", json={"x": 1}, timeout=5)
r.raise_for_status()
out.write_text(r.text, encoding=r.encoding or "utf-8")
PythonPathlibで保存先を確保し、テキストならwrite_text、バイナリならwrite_bytesを使います。
大きなファイルを送る(ストリーミング)
import requests
with open("bigdata.bin", "rb") as f:
r = requests.post("https://httpbin.org/post", data=f, timeout=60)
r.raise_for_status()
print(r.status_code)
Python巨大データはファイルオブジェクトを渡してストリーミング送信できます。サーバの受け入れ上限とタイムアウトを合わせて設定します。
HTTPS検証・プロキシ
import requests
# 証明書検証は基本True(既定のまま)
r = requests.post("https://httpbin.org/post", json={"x": 1}, timeout=5, verify=True)
# 社内プロキシ経由
proxies = {"https": "http://proxy.example:8080"}
r = requests.post("https://httpbin.org/post", json={"x": 1}, proxies=proxies, timeout=5)
Pythonverify=Falseはセキュリティが下がるため原則避けます。必要なら信頼できる証明書を事前に設定します。
よくある落とし穴の回避
ボディ形式の取り違え
APIがJSONを要求しているのにdata=で送ると失敗します。JSONならjson=、フォームならdata=を使い分けます。
タイムアウト未指定で固まる
ネットワーク不調で待ち続ける事故を防ぐため、timeoutは常に付けます。通常は数秒、重い処理は長めに。
失敗の見落とし
status_codeだけの確認だと流れてしまうことがあります。raise_for_statusを必ず呼び、例外で検出します。
重複実行の危険(非冪等)
POSTは同じリクエストを再送すると「登録が二重」などになり得ます。再試行は慎重に、可能ならサーバのidempotency-keyや重複防止の仕組みを使います。
例題で身につける(定番から実務まで)
例題1:JSON投稿+応答検証
import requests
resp = requests.post("https://httpbin.org/post", json={"user": "taro", "score": 88}, timeout=5)
resp.raise_for_status()
print("OK:", resp.status_code)
print(resp.json()["json"]) # サーバが受け取ったJSON
Python例題2:フォーム投稿+ヘッダー指定
import requests
form = {"username": "taro", "password": "secret"}
headers = {"Accept": "application/json"}
resp = requests.post("https://httpbin.org/post", data=form, headers=headers, timeout=5)
resp.raise_for_status()
print(resp.json()["form"])
Python例題3:ファイルアップロード(multipart/form-data)
import requests
with open("avatar.png", "rb") as f:
files = {"avatar": ("avatar.png", f, "image/png")}
r = requests.post("https://httpbin.org/post", files=files, timeout=15)
r.raise_for_status()
print(r.json()["files"])
Python例題4:Session+リトライで安定化
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
session = requests.Session()
session.headers.update({"Authorization": "Bearer TOKEN"})
retry = Retry(total=3, backoff_factor=0.5, status_forcelist=[500, 502, 503, 504])
session.mount("https://", HTTPAdapter(max_retries=retry))
resp = session.post("https://httpbin.org/post", json={"ping": "pong"}, timeout=5)
resp.raise_for_status()
print(resp.json())
Pythonまとめ
requests.postは「サーバへデータを送る」ための基本メソッドです。json=とdata=でボディ形式を正しく選び、ヘッダーを整え、timeoutとraise_for_statusで壊れない通信にする。ファイルはfilesでmultipartに、Sessionで認証やクッキーを維持、必要に応じて安全な再試行を組み合わせる。これらの型を押さえれば、初心者でも短く、確実なAPI連携が書けます。
