この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:5
ページ更新者:atom
更新日時:2026-09-07 06:30:57

タイトル: cookieの値の設定と取得
SEOタイトル: Python で Cookie を扱う|requests の Session と http.cookies

この記事の要点
  • Cookie を「送る側(クライアント)」なら requests.Session を使えば自動で保持される
  • 1 回だけ付けたいなら requests.get(url, cookies={"key": "value"})
  • 受け取った Cookie は res.cookies。属性まで見たいなら session.cookies を走査する
  • Cookie を「返す側(サーバー)」なら Set-Cookie ヘッダーを組み立てる。標準の http.cookies が使える
  • ログイン状態をファイルに残すなら http.cookiejar.LWPCookieJar で保存・読み込みする

Session を使うのが基本

Cookie は「1 回のリクエストの設定」ではなく「やり取りをまたいで持ち回る状態」です。requests.Session を使うと、サーバーから返ってきた Cookie を自動で保存し、次のリクエストに付けてくれます。

import requests

session = requests.Session()

# 1. ログイン。返ってきたセッション Cookie が session に保存される
session.post("https://example.com/login",
             data={"username": "taro", "password": "secret"},
             timeout=10)

# 2. 以降のリクエストには自動で付く
res = session.get("https://example.com/mypage", timeout=10)
print(res.status_code)

print(session.cookies.get_dict())   # {'sessionid': 'abc123'}
session.close()

requests.get() を単発で呼ぶ方法では Cookie が保持されないため、ログインが必要なページは必ず 401 / ログイン画面に戻されます。

Cookie を明示的に設定する

import requests

# その 1 回だけ付ける
res = requests.get("https://example.com/",
                   cookies={"lang": "ja", "theme": "dark"},
                   timeout=10)

# Session に常設する(以降すべてのリクエストに付く)
session = requests.Session()
session.cookies.set("lang", "ja")
session.cookies.set("sessionid", "abc123",
                    domain="example.com", path="/")

# ヘッダーとして直接書くこともできるが、Session の管理から外れるので非推奨
res = requests.get(url, headers={"Cookie": "lang=ja; theme=dark"}, timeout=10)

domain を指定しないと、そのリクエストのホストにだけ送られます。複数のサブドメインをまたぐ場合は明示してください。

受け取った Cookie を読む

res = requests.get("https://example.com/", timeout=10)

print(res.cookies.get_dict())        # そのレスポンスで設定されたものだけ
print(res.cookies.get("sessionid"))  # 無ければ None
print(res.headers.get("Set-Cookie")) # 生のヘッダー文字列

# 属性まで見たいときは 1 個ずつ走査する
for c in res.cookies:
    print(c.name, c.value, c.domain, c.path, c.secure, c.expires)
書き方返るもの
res.cookiesそのレスポンスで新しく設定された Cookie
session.cookiesこれまでに蓄積されたすべての Cookie
res.request.headers["Cookie"]実際に送信した Cookie ヘッダー

「送ったつもりが送られていない」場合は 3 番目を確認します。ドメインやパスが合っていないと、保持されていても送信対象から外れます。

削除と更新

session.cookies.set("lang", "en")          # 同じ名前なら上書き
del session.cookies["lang"]                # 1 個削除
session.cookies.clear()                    # 全削除(ログアウト相当)
session.cookies.clear("example.com")       # ドメイン単位で削除

print("lang" in session.cookies.get_dict())   # False

ログイン状態をファイルに保存する

import http.cookiejar
import os
import requests

JAR_PATH = "cookies.txt"

jar = http.cookiejar.LWPCookieJar(JAR_PATH)
if os.path.exists(JAR_PATH):
    jar.load(ignore_discard=True)          # 前回の Cookie を復元

session = requests.Session()
session.cookies = jar                      # Session に差し込む

session.get("https://example.com/mypage", timeout=10)

jar.save(ignore_discard=True)              # セッション Cookie も含めて保存

ignore_discard=True を付けないと、ブラウザを閉じたら消える種類の Cookie が保存されません。保存したファイルはログイン情報そのものなので、権限を絞り、リポジトリに入れないでください。

サーバー側で Cookie を返す

Web アプリを自作する場合は Set-Cookie ヘッダーを組み立てます。標準ライブラリの http.cookies が属性のエスケープまで面倒を見てくれます。

from http.cookies import SimpleCookie

cookie = SimpleCookie()
cookie["sessionid"] = "abc123"
cookie["sessionid"]["path"] = "/"
cookie["sessionid"]["max-age"] = 3600
cookie["sessionid"]["httponly"] = True     # JavaScript から読めなくする
cookie["sessionid"]["secure"] = True       # HTTPS のときだけ送らせる
cookie["sessionid"]["samesite"] = "Lax"    # 別サイトからの送信を制限

print(cookie.output(header="Set-Cookie:"))
# Set-Cookie: sessionid=abc123; HttpOnly; Max-Age=3600; Path=/; SameSite=Lax; Secure

# 受け取ったヘッダーを解析する
incoming = SimpleCookie("lang=ja; theme=dark")
print(incoming["lang"].value)               # ja
属性意味推奨
HttpOnlyJavaScript から読めなくするセッション ID には必ず付ける
SecureHTTPS のときだけ送る本番では付ける
SameSite他サイト由来のリクエストで送るかLax が既定的。決済系は Strict
Max-Age / Expires有効期限省略するとブラウザを閉じるまで
Path / Domain送信対象の範囲広げすぎない

よくある詰まりどころ

  • Session を使っていない — 単発の requests.get() では Cookie が引き継がれない
  • リダイレクト先で消える — allow_redirects=False にして途中の Set-Cookie を確認する
  • ログインが JavaScript 経由 — フォーム POST ではなく API を叩いている。ブラウザの開発者ツールで実際のリクエストを見る
  • CSRF トークンが必要 — ログインページを一度 GET してトークンを取り出し、POST に含める
  • 日本語や記号が入る値 — urllib.parse.quote() でエンコードしてから入れる

関連