PythonでWebサービスやAPIと連携するには、HTTPの理解が欠かせません。
本記事ではHTTPのGETとPOSTの違いを、Pythonのrequestsライブラリを使いながら、図解たっぷりで丁寧に解説します。
初心者でも「なぜそう書くのか」が腑に落ちるように、URLとボディの違い、セキュリティの注意点、実践的なサンプルコードまで一気に学んでいきます。
PythonでHTTP通信を学ぶメリット
Python初心者がHTTPを理解すべき理由

Pythonを学び始めた方にとって、文法や基本的なデータ構造に続いて理解しておきたいのがHTTP通信です。
Pythonは次のような場面で頻繁にHTTPを使います。
- Web APIと連携してデータを取得する
- Webサイトから情報を取得するスクレイピングツールを作る
- DjangoやFastAPIなどでWebアプリケーションを開発する
これらはどれも、裏側ではHTTPリクエストとHTTPレスポンスが行き交っています。
PythonのコードからAPIを呼び出すとき、単にサンプルをコピーするのではなく、「なぜここでGETなのか」「なぜここはPOSTなのか」が理解できると、トラブルにも強くなります。
特にGETとPOSTの違いは、HTTPを学ぶうえでの最初のハードルであり、かつ最重要ポイントです。
ここをきちんと押さえることで、今後のPythonでのWeb開発やデータ取得の理解がぐっと楽になります。
Web APIとPythonの基本的な関係

Web APIとは、インターネット越しにデータや機能を提供してくれる仕組みです。
PythonからWeb APIを呼び出すとき、一般的にはrequestsライブラリを使ってHTTPリクエストを送信します。
このとき、Pythonのコードは次のような情報をAPIサーバに送ります。
- メソッド(GET・POSTなど)
- URL(どのAPIを呼ぶか)
- ヘッダ(認証情報や送信データの形式など)
- ボディ(必要に応じて送信するデータ)
そして、サーバからはステータスコードやJSON形式のデータなどが返ってきます。
この「メソッド」にあたる部分で最もよく使われるのがGETとPOSTであり、両者の違いを理解することが、API連携の第一歩になります。
HTTPメソッドの基本
HTTPとは何かをPython目線で整理

HTTP(HyperText Transfer Protocol)は、Webでデータをやり取りするためのルールです。
ブラウザもPythonスクリプトも、このHTTPという共通ルールに従ってサーバと会話しています。
Pythonから見たHTTPのポイントは次の通りです。
- PythonはHTTPを「リクエストを送るための手段」として使う
- HTTPリクエストにはメソッド・URL・ヘッダ・ボディなどが含まれる
- サーバはそれに対してステータスコード・ヘッダ・ボディを返す
Pythonのrequestsライブラリは、このHTTPの細かい部分を隠して、シンプルなメソッド(cst-code>getやpost)として提供してくれます。
ですから、HTTPの概念を押さえたうえでrequestsを使うと、「黒魔術」ではなく「意味の分かるコード」になっていきます。
GETとPOSTの位置づけと役割

HTTPには複数のメソッドがありますが、PythonでAPIを触るとき最も頻繁に登場するのがGETとPOSTです。
簡単に言うと、役割は次のように整理できます。
- GET: データを取得するためのメソッド
- POST: データを送信して新しいリソースを作ったり、処理を依頼するメソッド
他にもPUTやDELETEなどがありますが、まずはGETとPOSTさえ区別できれば、多くのAPIを扱えるようになります。
実際のAPIドキュメントでも「このエンドポイントはGETで呼び出してください」「このエンドポイントはPOSTです」と書かれているので、メソッドを間違えると、そもそもAPIが動かないということもよくあります。
GETメソッドとは
GETの基本的な仕組み

GETメソッドは、サーバから情報を取り出すために使うメソッドです。
特徴を整理すると、次のようになります。
- 主な用途は「読み取り」「検索」
- URLにクエリパラメータとして条件を付ける
- 一般的にサーバ側の状態を変更しない(副作用がないことが期待される)
たとえば、次のようなURLを想像してみてください。
https://api.example.com/users?name=taro&limit=10
このURLでは、「ユーザ一覧のうち、name=taroに一致するものをlimit=10件まで返してほしい」という意味になります。
GETでは、このように取得条件をURLの一部として書くのが基本的な考え方です。
Python(requests)でのGETリクエスト例

PythonでGETリクエストを送るには、requests.getを使います。
見やすさのため、公共API(例: httpbin)を使ったシンプルな例を示します。
import requests
# ベースとなるURL
url = "https://httpbin.org/get"
# クエリパラメータを辞書で指定
params = {
"name": "taro",
"limit": 10
}
# GETリクエストを送信
response = requests.get(url, params=params)
# ステータスコードを確認
print("ステータスコード:", response.status_code)
# レスポンスボディ(JSON)を表示
print("レスポンスJSON:")
print(response.json())
ステータスコード: 200
レスポンスJSON:
{'args': {'limit': '10', 'name': 'taro'}, 'headers': {...}, 'url': 'https://httpbin.org/get?name=taro&limit=10', ...}
この例では、params引数に辞書を渡すと、自動的にURLのクエリパラメータとして付与されます。
コード中でURL文字列を自分で結合する必要がないため、安全で読みやすい書き方になります。
クエリパラメータの使い方と注意点

GETで条件を指定する際に使うのがクエリパラメータです。
Pythonではparams引数に辞書で指定するのが基本ですが、使う際にはいくつか注意点があります。
まず、URLには実質的な長さ制限があるという点です。
ブラウザやサーバによって許容される最大長は異なりますが、非常に長いクエリパラメータを付けるとエラーになることがあります。
そのため、大量のデータや長文テキストを送る用途にはGETは向きません。
また、クエリパラメータはURLにそのまま表示されるため、ログやブラウザの履歴、ブックマークなどに残りやすいです。
パスワードやクレジットカード番号など、機密性の高い情報をクエリパラメータに含めるのは避けなければなりません。
これについては後ほどセキュリティの章で詳しく説明します。
POSTメソッドとは
POSTの基本的な仕組み

POSTメソッドは、サーバにデータを送信し、何らかの処理やリソース作成を依頼するメソッドです。
特徴としては次のようなポイントがあります。
- 主な用途は「新規作成」「処理の実行」
- URLではなく、ボディにデータを入れて送信する
- サーバ側の状態が変化する(副作用があることが多い)
たとえばユーザ登録フォームを考えると、nameやemailなどの情報を送って、新しいユーザを作ってもらうことになります。
このような「何かを登録する・変更する」場面では、GETではなくPOSTが使われます。
Python(requests)でのPOSTリクエスト例

PythonでPOSTリクエストを送るには、requests.postを使います。
フォーム送信に近い形(アプリケーション/x-www-form-urlencoded)のサンプルを示します。
import requests
url = "https://httpbin.org/post"
# 送信するデータ(フォーム形式)
data = {
"name": "taro",
"age": 20
}
# POSTリクエストを送信
response = requests.post(url, data=data)
print("ステータスコード:", response.status_code)
print("レスポンスJSON:")
print(response.json())
ステータスコード: 200
レスポンスJSON:
{'form': {'age': '20', 'name': 'taro'}, 'json': None, 'url': 'https://httpbin.org/post', ...}
ここで渡しているdata引数は、HTTPリクエストのボディ部分として送信されます。
GETの場合はparamsでしたが、POSTではdataやjsonといった引数を使い分けます。
ボディにデータを送る意味と用途

POSTではボディにデータを入れて送ると説明しましたが、これは次のような意味を持ちます。
まず、ボディはURLよりも自由度が高く、データ量の制約も比較的緩やかです。
そのため、長文テキスト、複数フィールドを持つフォームデータ、JSON形式の複雑なオブジェクトなどを送るのに適しています。
さらに、URLに比べてボディは直接目に触れにくいため、ログや履歴への露出も限定的になります(もちろん、サーバ側やプロキシでログされる可能性はありますが、URLよりはコントロールしやすいです)。
具体的な用途としては次のようなものがあります。
- ユーザ登録やログインフォームの送信
- 注文情報や決済情報の送信
- 検索条件が非常に複雑な場合の検索リクエスト
- JSON APIに対して、複雑なパラメータを渡す処理
このように、「何かを依頼する」「状態を変える」処理にはPOSTというイメージを持つと覚えやすくなります。
GETとPOSTの違いを図解で理解
URLとボディの違いを図で比較

GETとPOSTの実際の違いは、「どこにデータを載せるか」に集約されます。
表形式で整理するとイメージしやすくなります。
| 項目 | GET | POST |
|---|---|---|
| 主な用途 | データ取得 | データ送信・作成・処理 |
| パラメータの場所 | URLのクエリパラメータ | リクエストボディ |
| ブラウザの操作 | ブックマークしやすい | ブックマークには向かない |
| 一般的な期待 | 状態を変えない(参照のみ) | 状態が変わる(更新・作成など) |
同じ内容のパラメータでも、GETではURLに、POSTではボディに載るという違いを押さえておくと、APIドキュメントを読むときも混乱しにくくなります。
可視性(見える情報)とセキュリティの違い

GETとPOSTの大きな違いとして、どこまで情報が「見える」かという点があります。
GETのクエリパラメータはURLに含まれるため、次の場所に残りやすいです。
- ブラウザのアドレスバー
- ブラウザの履歴
- ブックマーク
- Webサーバやプロキシのアクセスログ
一方で、POSTのボディはアドレスバーには表示されません。
開発者ツールを開けば確認できますし、サーバ側のログにも残ることはありますが、URLほどあちこちにコピーされにくいという違いがあります。
ただし、「POSTだから安全」というわけではありません。
後述するように、HTTPSで暗号化されていない場合、GETもPOSTも通信経路上では丸見えです。
この点を誤解していると危険ですので、「可視性」と「暗号化」は分けて考える必要があります。
キャッシュやブックマークの挙動の違い

ブラウザやプロキシは、一般的にGETリクエストの結果をキャッシュしやすいという特徴があります。
同じURLに対して再度アクセスすると、場合によってはサーバに問い合わせずにキャッシュから結果を返します。
一方、POSTリクエストはサーバ側の状態を変える可能性があるため、ブラウザは安易にキャッシュしません。
フォーム送信後にページを再読み込みすると、「フォームの再送信になりますがよろしいですか?」といった警告が出るのはこのためです。
この違いは、PythonでAPIを叩くときにも影響します。
例えば、同じ条件で何度も結果を取得したいだけならGETを使うのが自然ですし、毎回新しいデータを登録する処理ならPOSTを使うべきです。
GETとPOSTの使い分け方
いつGETを使うべきか

GETを使うのは、「データを読むだけで、サーバ側の状態を変えない処理」が基本です。
Pythonでの具体的な場面としては、次のようなものが挙げられます。
- 商品一覧を取得するAPI呼び出し
- ニュース記事の一覧・詳細を取得する
- 天気情報や株価などの最新データを取得する
- 画像やPDFファイルなどの静的ファイルをダウンロードする
また、URLで結果を共有したい場合もGETが向いています。
例えば、検索条件をURLに含めておけば、そのURLを他人に送ったりブックマークしたりするだけで、同じ検索結果を再現できます。
いつPOSTを使うべきか

POSTを使うのは、「サーバに何かを依頼し、その結果としてサーバ側の状態が変わる処理」です。
Pythonでの典型的なケースは次の通りです。
- ユーザ登録やログイン情報の送信
- 商品の注文や予約データの送信
- 問い合わせフォームの送信
- 機械学習APIに画像やテキストを送り、分類・分析結果をもらう
クライアントから見れば「データを送って結果をもらう」という点ではGETと似ているように見えますが、サーバ側に新しい記録が追加されたり、既存のデータが変化する場合はPOSTを選ぶべきです。
よくある誤用とアンチパターン

実務で見かけるよくある誤用も押さえておきます。
1つ目は、副作用のある処理にGETを使ってしまうことです。
例えば、次のようなURLを想像してください。
https://example.com/delete_user?id=123
これをGETで実行すると、「URLを踏むだけでユーザが削除される」という危険な状態になります。
検索エンジンのクローラがアクセスしただけでデータが消える、といった事故にもつながりかねません。
このような処理にはPOST(あるいはDELETE)を使うのが望ましいです。
2つ目は、パスワードやトークンをクエリパラメータに載せてしまうことです。
URLに含めると、ログや履歴に残りやすく、情報漏えいのリスクが高くなります。
認証情報や機密データは、ヘッダ(例: Authorizationヘッダ)やボディに載せるのが適切です。
セキュリティとGET・POST
パスワード送信にGETを使ってはいけない理由

パスワードやトークンなどの機密情報をGETで送ると、次のような問題が発生します。
- URLとしてブラウザ履歴に保存される
- ブックマークされる可能性がある
- Webサーバやプロキシのアクセスログにそのまま残る
- 画面共有やスクリーンショットで簡単に漏えいする
「URLはあちこちにコピーされやすい」という特性があるため、そこに秘密情報を載せてはいけません。
パスワード送信には必ずPOSTを利用し、さらにHTTPSで暗号化することが必須です。
HTTPSとGET・POSTの関係

ここで誤解しがちなポイントを整理します。
GETだから危険でPOSTだから安全、ということはありません。
安全性を左右するのは、HTTPかHTTPSかという点です。
- HTTP(GET/POST問わず): 通信内容が暗号化されず、第三者に丸見え
- HTTPS(GET/POST問わず): 通信内容が暗号化され、途中で盗み見られても中身は読めない
つまり、パスワードをPOSTで送っていても、HTTPのままだと盗聴可能です。
一方、HTTPSであれば、GETのクエリパラメータも含めて丸ごと暗号化されます。
ただし、HTTPSでもURLの一部はブラウザ履歴やサーバログには残るので、クエリパラメータに機密情報を入れないという原則は変わりません。
ログ・履歴に残る情報への注意点

セキュリティを考えるうえで重要なのは、どこに情報が残りうるかを理解しておくことです。
GETのクエリパラメータは、次の場所に残りやすいです。
- ブラウザ履歴・ブックマーク
- Webサーバのアクセスログ
- 途中のプロキシサーバのログ
POSTのボディは通常、ブラウザ履歴やブックマークには残りませんが、サーバ側でアプリケーションログとして記録される場合があります。
また、デバッグ用にPython側でログ出力してしまったりすると、ローカルマシン上に平文のパスワードが残ることもあります。
そのため、PythonでHTTP通信を書くときにも、ログに何を出力するかには注意が必要です。
デバッグ中にprint(response.request.body)のようなコードを追加する場合でも、本番環境に残さないよう気を付けましょう。
Pythonでの実践パターン集
PythonでAPIを呼び出すGETの具体例

ここからは、Pythonでの具体的なコードパターンを見ていきます。
まずは、典型的なGETの例として、架空の天気APIを呼び出すコード例を示します。
import requests
# 架空の天気APIのエンドポイント
BASE_URL = "https://api.example.com/weather"
def get_weather(city: str, api_key: str) -> dict:
"""
指定した都市の天気情報を取得する関数です。
GETメソッドを使い、都市名とAPIキーをクエリパラメータとして送信します。
"""
params = {
"city": city,
"apikey": api_key,
"units": "metric" # 摂氏を指定
}
# GETリクエストの送信
response = requests.get(BASE_URL, params=params)
response.raise_for_status() # エラーがあれば例外を発生させる
return response.json()
if __name__ == "__main__":
# 実際にはAPIキーは環境変数などから読むのが望ましいです
api_key = "YOUR_API_KEY"
city = "Tokyo"
weather = get_weather(city, api_key)
print(f"{city}の現在の天気情報:")
print(weather)
Tokyoの現在の天気情報:
{'temp': 23.4, 'humidity': 60, 'description': 'Cloudy', ...}
このパターンでは、paramsに条件やAPIキーをまとめて指定し、読み取り専用の情報取得としてGETを使っています。
Pythonでフォーム送信を再現するPOSTの具体例

次に、問い合わせフォームの送信をPythonから再現するPOSTの例を見てみましょう。
import requests
CONTACT_URL = "https://example.com/api/contact"
def send_contact(name: str, email: str, message: str) -> bool:
"""
問い合わせフォームを送信する関数です。
ブラウザからのフォーム送信と同様に、POSTメソッドでデータを送ります。
"""
data = {
"name": name,
"email": email,
"message": message
}
# フォームデータとして送信
response = requests.post(CONTACT_URL, data=data)
# ステータスコード200台であれば成功とみなす
return response.ok
if __name__ == "__main__":
result = send_contact(
name="山田太郎",
email="taro@example.com",
message="資料請求をお願いします。"
)
if result:
print("問い合わせを送信しました。")
else:
print("問い合わせの送信に失敗しました。")
問い合わせを送信しました。
この例では、data引数を使って、フォームと同じ形式でデータを送信しています。
サーバ側が想定する形式に合わせて、フォームデータかJSONかを選ぶことが重要です。
JSONとフォームデータの違いと送信方法

POSTでボディを送るとき、Pythonのrequestsでは主に次の2通りの送り方があります。
1つはフォームデータ(application/x-www-form-urlencoded)として送る方法で、先ほどのdata=...がそれに当たります。
ブラウザのフォーム送信と互換性があり、古いAPIやWebアプリでよく使われます。
もう1つはJSON(application/json)として送る方法で、json=...引数を使います。
モダンなWeb APIでは、こちらが推奨されることが多いです。
実際のコード例を比較してみます。
import requests
url = "https://httpbin.org/post"
# フォームデータとして送る場合
form_data = {
"name": "taro",
"age": 20
}
response_form = requests.post(url, data=form_data)
# JSONとして送る場合
json_data = {
"name": "taro",
"age": 20
}
response_json = requests.post(url, json=json_data)
print("フォームデータとして送信した場合のレスポンス:")
print(response_form.json()["form"]) # 'form'キーにデータが入る
print("JSONとして送信した場合のレスポンス:")
print(response_json.json()["json"]) # 'json'キーにデータが入る
フォームデータとして送信した場合のレスポンス:
{'age': '20', 'name': 'taro'}
JSONとして送信した場合のレスポンス:
{'age': 20, 'name': 'taro'}
このように、送信形式によって、サーバ側の受け取り方やパース方法が変わってきます。
APIドキュメントにContent-Type: application/jsonと書かれている場合はjson=...を、そうでなければdata=...を使う、というのが1つの目安です。
まとめ
GETとPOSTはどちらもHTTPメソッドですが、「何の目的で」「どこにデータを載せるか」が明確に異なります。
Pythonのrequestsでは、取得専用の処理にはget(..., params=...)を、データ送信や処理依頼にはpost(..., data=... / json=...)を使い分けることが基本です。
また、セキュリティの観点からは、機密情報をクエリパラメータに入れないこと、HTTPSを必ず利用することが重要です。
この記事の図解とサンプルコードを参考にしながら、自分でも小さなスクリプトを書いて試してみると、GETとPOSTの違いがより実感として理解できるようになります。
