Pythonで外部サービスと連携するとき、最初にぶつかるのがHTTP通信の扱いです。
標準ライブラリのurllibでも実現できますが、コードが長くなりがちです。
requestsは「人間が読めるコード」でHTTPリクエストを書ける人気ライブラリで、Web API連携では事実上の標準といえます。
この記事では、インストールから実践的なAPI連携まで、ステップを追って詳しく解説します。
Pythonのrequestsとは
requestsとは

Pythonのrequestsライブラリは、HTTP通信を簡単かつ直感的に扱うための外部ライブラリです。
ブラウザが裏側で行っている「サーバーとのやりとり」を、Pythonから自動化する道具と考えるとイメージしやすいです。
例えば、次のような用途でよく使われます。
- Webサイトから情報を取得するスクレイピングの前段階としてHTMLを取得する
- REST APIやGraphQL APIと連携して、JSON形式のデータをやり取りする
- ファイルのアップロードやダウンロードを自動化する
- 認証付きのWebサービスと連携する
HTTPメソッド(GET、POST、PUT、DELETEなど)ごとに関数が用意されており、ほぼ1行でリクエストが書ける点が最大の特徴です。
インストール方法
requestsは標準ライブラリではないため、最初にインストールが必要です。
もっとも一般的なのはpipを使う方法です。
# requests をインストール
pip install requests
# バージョンを確認
pip show requests
仮想環境を使っている場合は、必ず仮想環境を有効化してからインストールしてください。
企業やチームで開発する場合、プロジェクトごとに仮想環境を分けて依存関係を管理することが重要です。
pip以外にも、PoetryやPipenvなどのツールから依存パッケージとして指定してインストールすることもできます。
requestsの基本的な使い方
シンプルなGETリクエストの書き方

最も基本的な操作は、URLに対してGETリクエストを送り、レスポンスを取得することです。
ブラウザでURLを開くのと本質的には同じですが、それをPythonから行います。
import requests # ライブラリを読み込む
# 取得したいURL
url = "https://httpbin.org/get"
# GETリクエストを送信
response = requests.get(url)
# ステータスコードを確認(200なら成功の意味)
print("Status:", response.status_code)
# レスポンスボディ(テキスト)を表示
print("Body:", response.text[:200]) # 長いので先頭200文字だけ表示
Status: 200
Body: {
"args": {},
"headers": {
...
上記の例では、requests.getがHTTP GETリクエストを送り、その結果がresponseオブジェクトに格納されます。
レスポンスの本文を文字列として扱いたい場合はresponse.text、バイト列として扱いたい場合はresponse.contentを使います。
クエリパラメータ(params)の指定方法

GETリクエストでは、URLの?以降にクエリパラメータを付けてサーバーに条件を渡します。
requestsでは、このクエリパラメータをparams引数でシンプルに指定できます。
import requests
url = "https://httpbin.org/get"
# クエリパラメータを辞書で指定
params = {
"keyword": "python",
"page": 2
}
response = requests.get(url, params=params)
print("Requested URL:", response.url) # 実際に送信されたURLを確認
print("JSON:", response.json())
Requested URL: https://httpbin.org/get?keyword=python&page=2
JSON: {'args': {'keyword': 'python', 'page': '2'}, ...}
paramsに辞書を渡すと、自動的にURLエンコードされて結合されるため、自分で?や&を組み立てる必要がありません。
特に、検索条件など複数のパラメータを扱うときに安全で便利です。
POSTリクエストとフォームデータ(data)の送信

フォーム送信などでデータをサーバーに送る場合は、POSTリクエストを使います。
requestsではrequests.postとdata引数を使います。
import requests
url = "https://httpbin.org/post"
# 送信するフォームデータ
data = {
"username": "alice",
"password": "secret123"
}
response = requests.post(url, data=data)
print("Status:", response.status_code)
print("JSON:", response.json()["form"]) # 送信されたフォーム内容を確認
Status: 200
JSON: {'password': 'secret123', 'username': 'alice'}
data引数も辞書で渡せば、application/x-www-form-urlencoded形式のフォームデータとして自動変換されて送信されます。
ログインフォームや問い合わせフォームなど、Webアプリでよくある形式です。
JSON APIとの連携方法
JSONレスポンスの取得と解析

最近のWeb APIでは、レスポンスとしてJSON形式が使われることがほとんどです。
requestsはresponse.json()メソッドで、JSON文字列を自動的にPythonの辞書やリストに変換してくれます。
import requests
url = "https://httpbin.org/json"
response = requests.get(url)
# レスポンスをそのまま文字列として確認
print("Raw text:", response.text[:100])
# JSONとしてパースしてPythonのオブジェクトにする
data = response.json()
print("Keys:", data.keys())
print("Title:", data.get("slideshow", {}).get("title"))
Raw text: {
"slideshow": {
"author": "Yours Truly",
Keys: dict_keys(['slideshow'])
Title: Sample Slide Show
JSON APIとやり取りする場合、まずresponse.json()で辞書化し、その上で通常のPython操作(キーアクセス、ループなど)を行うのが定番パターンです。
JSONデータの送信

サーバー側にJSON形式でデータを送る場合は、json引数を使うと便利です。
requestsが自動でJSONにシリアライズし、ヘッダーも適切に設定してくれます。
import requests
url = "https://httpbin.org/post"
payload = {
"name": "Alice",
"age": 30,
"languages": ["Python", "JavaScript"]
}
# json= を使うと自動で JSON に変換 + Content-Type ヘッダー設定
response = requests.post(url, json=payload)
data = response.json()
print("Received JSON:", data["json"])
print("Content-Type:", data["headers"]["Content-Type"])
Received JSON: {'age': 30, 'languages': ['Python', 'JavaScript'], 'name': 'Alice'}
Content-Type: application/json
data=とjson=は意味が異なる点に注意してください。
json=はJSONとして送るための専用引数であり、JSON APIでは基本的にこちらを使うとよいです。
ヘッダーと認証の設定
リクエストヘッダー(headers)の指定方法

APIによっては、特定のヘッダーが必須となることがあります。
例えば、User-Agentを指定したり、APIキーをヘッダーで渡すパターンです。
requestsではheaders引数に辞書を渡すことで簡単に設定できます。
import requests
url = "https://httpbin.org/headers"
custom_headers = {
"User-Agent": "MyApp/1.0",
"X-API-KEY": "dummy-api-key-12345"
}
response = requests.get(url, headers=custom_headers)
data = response.json()
print("Headers seen by server:")
for k, v in data["headers"].items():
print(k, ":", v)
Headers seen by server:
Accept-Encoding : gzip, deflate
Host : httpbin.org
User-Agent : MyApp/1.0
X-Api-Key : dummy-api-key-12345
...
ヘッダーは認証やコンテンツの形式、クライアント情報など、API連携で極めて重要な情報を伝える役割があります。
APIドキュメントに記載されている必須ヘッダーを、headersに素直に写経するイメージで実装します。
ベーシック認証とトークン認証の実装

APIでよく使われる認証方式として、ベーシック認証とトークン認証があります。
ベーシック認証(Basic Auth)
ベーシック認証は、ユーザー名とパスワードをBase64でエンコードしたものをAuthorizationヘッダーに載せて送る仕組みです。
requestsには専用のauth引数が用意されています。
import requests
from requests.auth import HTTPBasicAuth
url = "https://httpbin.org/basic-auth/user123/pass123"
# ユーザー名とパスワードを指定
auth = HTTPBasicAuth("user123", "pass123")
response = requests.get(url, auth=auth)
print("Status:", response.status_code)
print("JSON:", response.json())
Status: 200
JSON: {'authenticated': True, 'user': 'user123'}
認証に失敗すると、通常はステータスコード401(Unauthorized)が返ってきます。
トークン認証(Bearer Tokenなど)
より安全な方式として、アクセストークン(長いランダムな文字列)を用いるケースが多くなっています。
多くはAuthorization: Bearer <token>の形式で送ります。
import requests
url = "https://api.example.com/resource"
token = "your_access_token_here"
headers = {
"Authorization": f"Bearer {token}"
}
response = requests.get(url, headers=headers)
print("Status:", response.status_code)
トークンは通常、事前にユーザー登録やOAuthフローを通じて取得します。
実際のコードではトークンをソースコードにベタ書きせず、環境変数や設定ファイルから読み込むようにすると安全です。
タイムアウトとエラーハンドリング
timeoutの設定と意味

ネットワークやサーバーの状態によっては、レスポンスがなかなか返ってこないことがあります。
タイムアウトを設定せずに待ち続けると、プログラムが固まったように見えてしまうため、実運用ではtimeout指定がほぼ必須です。
import requests
url = "https://httpbin.org/delay/3" # 3秒待ってから応答するAPI
try:
# 最大2秒だけ待つ(timeout=2)
response = requests.get(url, timeout=2)
print("Status:", response.status_code)
except requests.exceptions.Timeout:
print("Timeout 発生: 2秒以内に応答がありませんでした")
Timeout 発生: 2秒以内に応答がありませんでした
timeoutは「サーバーからの応答を待つ最大時間(秒)」を意味し、この時間を超えるとrequests.exceptions.Timeout例外が発生します。
重要な処理では、単に設定するだけでなく、例外を捕捉してリトライや代替処理を行うことが大切です。
ステータスコードと例外処理の基本

requestsでは、HTTPエラー(4xx, 5xx)そのものはデフォルトでは例外になりません。
response.status_codeを自分でチェックするか、response.raise_for_status()を使います。
import requests
url = "https://httpbin.org/status/404" # わざと 404 を返すURL
try:
response = requests.get(url, timeout=5)
# ステータスコードをチェックし、4xx/5xxなら例外を発生させる
response.raise_for_status()
print("成功:", response.text)
except requests.exceptions.HTTPError as e:
print("HTTPエラー:", e)
except requests.exceptions.RequestException as e:
# requests全般の例外(タイムアウト、接続エラーなど)をまとめて捕捉
print("通信エラー:", e)
HTTPエラー: 404 Client Error: NOT FOUND for url: https://httpbin.org/status/404
実務的なコードでは、「タイムアウト」「HTTPエラー(4xx/5xx)」「その他の通信エラー」をそれぞれ適切にハンドリングすることが重要です。
最低限、RequestExceptionを捕捉してログ出力するようにしておくと、原因調査がしやすくなります。
セッション(Session)の活用
Sessionオブジェクトで接続を再利用する

複数回リクエストを送る場合、requests.getなどを毎回呼ぶよりも、Sessionオブジェクトを使った方が効率的です。
Sessionは接続の再利用や共通ヘッダー・Cookieの自動送信などを行ってくれる便利なオブジェクトです。
import requests
session = requests.Session() # セッションを作成
# セッション全体で共通のヘッダーを設定
session.headers.update({"User-Agent": "MySessionApp/1.0"})
urls = [
"https://httpbin.org/get?i=1",
"https://httpbin.org/get?i=2",
"https://httpbin.org/get?i=3",
]
for url in urls:
response = session.get(url)
print(response.json()["args"])
{'i': '1'}
{'i': '2'}
{'i': '3'}
このようにsessionを通してリクエストを送ると、TCP接続が可能な限り再利用されるため、特にHTTPSでの繰り返しアクセスでは性能面で有利です。
Cookieや共通ヘッダーの管理方法

SessionはCookieや共通ヘッダーの管理にも向いています。
ログインが必要なサービスでは、まずログインリクエストを送り、以降のリクエストではそのセッションを使い回すのが典型です。
import requests
login_url = "https://httpbin.org/cookies/set/session_id/abc123"
check_url = "https://httpbin.org/cookies"
with requests.Session() as session:
# Cookieをセットする(本来はここでログインフォームをPOSTする)
session.get(login_url)
# Cookieが自動的に送信される
response = session.get(check_url)
print("Cookies on server:", response.json()["cookies"])
Cookies on server: {'session_id': 'abc123'}
with構文を使ってSessionを管理すると、使い終わった後に自動でクローズされるため安全です。
共通ヘッダーもsession.headers.update({...})で一括設定できます。
ファイルアップロードとダウンロード
ファイルアップロード

ファイルをサーバーに送信する場合、多くのAPIはmultipart/form-data形式を使います。
requestsではfiles引数で簡単に実現できます。
import requests
url = "https://httpbin.org/post"
# 送信するファイルを開く
# 実際の環境では存在するファイルパスに変更してください
file_path = "example.txt"
with open(file_path, "w", encoding="utf-8") as f:
f.write("Hello, file upload!") # デモ用にファイルを作成
with open(file_path, "rb") as f:
files = {"file": ("example.txt", f, "text/plain")}
response = requests.post(url, files=files)
print("Status:", response.status_code)
print("Uploaded file info:", response.json()["files"])
Status: 200
Uploaded file info: {'file': 'Hello, file upload!'}
files引数には「フィールド名: (ファイル名, ファイルオブジェクト, MIMEタイプ)」のタプルを渡すのが基本形です。
MIMEタイプ(例: image/png)を省略した場合、requestsが推測するか、空のまま送信されます。
バイナリデータのダウンロードと保存

画像やPDFなどのバイナリファイルをダウンロードするときは、response.contentやストリーミング機能を使います。
import requests
url = "https://httpbin.org/image/png"
response = requests.get(url)
# 画像をファイルに保存
output_path = "downloaded.png"
with open(output_path, "wb") as f:
f.write(response.content)
print("Saved to:", output_path)
Saved to: downloaded.png
大きなファイルの場合は、一度にメモリに読み込まず、チャンクごとに書き出す方法が安全です。
import requests
url = "https://httpbin.org/image/jpeg"
output_path = "downloaded_large.jpg"
with requests.get(url, stream=True) as r:
r.raise_for_status()
with open(output_path, "wb") as f:
# 1KBずつ書き出す
for chunk in r.iter_content(chunk_size=1024):
if chunk: # 空のチャンクをスキップ
f.write(chunk)
print("Saved to:", output_path)
Saved to: downloaded_large.jpg
stream=Trueを指定すると、レスポンスボディを逐次的に読み取れるようになり、大容量ファイルでもメモリ消費を抑えられます。
実践API例
GitHub APIにGETリクエストする例

GitHubはREST APIを公開しており、リポジトリ情報やユーザー情報を簡単に取得できます。
ここでは、公開リポジトリ情報を取得する基本的な例を示します。
import requests
# 取得したいリポジトリ(owner/repo)
owner = "psf"
repo = "requests"
url = f"https://api.github.com/repos/{owner}/{repo}"
response = requests.get(url)
response.raise_for_status() # エラーなら例外を投げる
data = response.json()
print("Repository:", data["full_name"])
print("Description:", data["description"])
print("Stars:", data["stargazers_count"])
print("URL:", data["html_url"])
Repository: psf/requests
Description: A simple, yet elegant, HTTP library.
Stars: 5xxxx
URL: https://github.com/psf/requests
このように、APIドキュメントに記載されたエンドポイントに対してrequests.getでアクセスし、response.json()で辞書として扱うのが基本パターンです。
認証付きでリポジトリ情報を取得する

GitHub APIは、未認証でもパブリックリポジトリ情報を取得できますが、アクセストークンで認証するとレートリミット(呼び出し制限)が緩和されるなどの利点があります。
ここでは、パーソナルアクセストークンを使う例を示します。
import os
import requests
owner = "psf"
repo = "requests"
url = f"https://api.github.com/repos/{owner}/{repo}"
# 環境変数から GitHub トークンを取得 (事前に設定しておく)
token = os.getenv("GITHUB_TOKEN")
headers = {}
if token:
headers["Authorization"] = f"Bearer {token}"
response = requests.get(url, headers=headers)
response.raise_for_status()
data = response.json()
print("Full name:", data["full_name"])
print("Private repo?:", data["private"])
print("Open issues:", data["open_issues_count"])
Full name: psf/requests
Private repo?: False
Open issues: 1xx
実運用では、トークンをソースコードに直接書かず、環境変数や秘密管理サービスから取得するのが重要です。
これにより、コードをGitなどで共有しても秘密情報が漏れることを防げます。
実践API例
天気予報APIからJSONデータを取得

天気予報APIは、練習にも実務にもよく使われる題材です。
ここでは、APIキー不要で利用できるOpen-Meteo APIを例に、緯度経度から現在の天気を取得してみます。
import requests
# 東京付近の座標(例)
latitude = 35.6895
longitude = 139.6917
url = "https://api.open-meteo.com/v1/forecast"
params = {
"latitude": latitude,
"longitude": longitude,
"current_weather": True
}
response = requests.get(url, params=params, timeout=10)
response.raise_for_status()
data = response.json()
current = data.get("current_weather", {})
print("Temperature:", current.get("temperature"), "°C")
print("Wind speed:", current.get("windspeed"), "km/h")
print("Time:", current.get("time"))
Temperature: 2x.x °C
Wind speed: 1x.x km/h
Time: 2025-12-23T12:00
paramsでクエリパラメータを指定し、JSONレスポンスから必要な値だけ抜き出す、という基本パターンのよい練習になります。
パラメータ指定で地域ごとの天気を取得

同じAPIを使って、複数の地域の天気を一度に取得してみます。
ここでは、都市名と座標を辞書で管理し、ループで回しながらAPIを呼び出します。
import requests
url = "https://api.open-meteo.com/v1/forecast"
cities = {
"Tokyo": (35.6895, 139.6917),
"Osaka": (34.6937, 135.5023),
"Fukuoka": (33.5902, 130.4017),
}
for city, (lat, lon) in cities.items():
params = {
"latitude": lat,
"longitude": lon,
"current_weather": True,
}
try:
response = requests.get(url, params=params, timeout=10)
response.raise_for_status()
except requests.exceptions.RequestException as e:
print(f"{city}: API呼び出しに失敗しました:", e)
continue
data = response.json()
current = data.get("current_weather", {})
temp = current.get("temperature")
wind = current.get("windspeed")
time = current.get("time")
print(f"{city} - {time} / Temp: {temp} °C / Wind: {wind} km/h")
Tokyo - 2025-12-23T12:00 / Temp: 2x.x °C / Wind: 1x.x km/h
Osaka - 2025-12-23T12:00 / Temp: 2x.x °C / Wind: 1x.x km/h
Fukuoka - 2025-12-23T12:00 / Temp: 2x.x °C / Wind: 1x.x km/h
このように、同じAPIをパラメータだけ変えて何度も呼び出す場合に、requestsのシンプルなインターフェースが非常に役立ちます。
さらに発展させれば、結果を表やグラフに整形してダッシュボードを作ることもできます。
まとめ
requestsライブラリを使うと、HTTP通信やAPI連携を少ないコードで、安全かつ読みやすく実装できます。
この記事では、GET/POSTの基本から、JSONの送受信、ヘッダーや認証、タイムアウトとエラー処理、セッション、ファイルのアップロード・ダウンロード、そしてGitHubや天気APIの実践例までを一通り紹介しました。
実際の開発では、ここで紹介したパターンを組み合わせるだけで、多くのWeb APIとやり取りできるようになります。
まずは小さなAPIから試し、レスポンスを確認しながら、少しずつ応用範囲を広げていってください。
