Flask Cheatsheet

Sessions and Cookies

Use this Flask reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

Sessions

Flask's default session is a client-side signed cookie (HMAC-SHA1 using SECRET_KEY). The data is visible to the client but cannot be tampered with. For server-side sessions, use flask-session.

from flask import session

# Read
user_id = session.get("user_id")           # None if key missing
theme   = session["theme"]                  # KeyError if missing

# Write
session["user_id"] = user.id
session["cart"] = [1, 2, 3]

# Delete one key
session.pop("user_id", None)               # safe pop (no error if missing)
del session["user_id"]                     # KeyError if missing

# Clear all session data
session.clear()

# Check membership
if "user_id" in session:
    ...

Session Configuration

Config KeyDefaultDescription
SECRET_KEYRequired. Signs the session cookie. Use a long random value.
SESSION_COOKIE_NAME"session"Cookie name
SESSION_COOKIE_DOMAINNoneDomain (None = current host only)
SESSION_COOKIE_PATHNoneCookie path (None = APPLICATION_ROOT)
SESSION_COOKIE_HTTPONLYTrueJS cannot read cookie
SESSION_COOKIE_SECUREFalseHTTPS-only; set True in production
SESSION_COOKIE_SAMESITENone"Lax", "Strict", or "None"
PERMANENT_SESSION_LIFETIME31 daystimedelta; only applies to permanent sessions
SESSION_REFRESH_EACH_REQUESTTrueRefresh cookie expiry on each request

Permanent Sessions

By default, the session cookie expires when the browser closes. Mark it as permanent to set a real expiry:

from datetime import timedelta

app.config["PERMANENT_SESSION_LIFETIME"] = timedelta(days=30)

@app.route("/login", methods=["POST"])
def login():
    session.permanent = True        # set before writing to session
    session["user_id"] = user.id
    return redirect(url_for("dashboard"))

Generating a Secure SECRET_KEY

python -c "import secrets; print(secrets.token_hex(32))"

Store in environment variable, never hard-code in source:

app.config["SECRET_KEY"] = os.environ.get("SECRET_KEY", "dev-only-key")

Custom Session Interface

from flask.sessions import SecureCookieSessionInterface

class MySessionInterface(SecureCookieSessionInterface):
    def should_set_cookie(self, app, session):
        return session.modified or session.permanent

app.session_interface = MySessionInterface()

Server-Side Sessions (flask-session)

pip install flask-session
from flask_session import Session

app.config["SESSION_TYPE"] = "filesystem"   # or "redis", "sqlalchemy", "memcached"
app.config["SESSION_FILE_DIR"] = "/tmp/flask_sessions"
app.config["SESSION_PERMANENT"] = False
# Note: SESSION_USE_SIGNER was deprecated and removed in flask-session 0.6+

Session(app)    # call after config

# Now session is server-side; usage is identical to client-side

Redis backend:

import redis
app.config["SESSION_TYPE"] = "redis"
app.config["SESSION_REDIS"] = redis.from_url("redis://localhost:6379")

SQLAlchemy backend:

app.config["SESSION_TYPE"] = "sqlalchemy"
app.config["SESSION_SQLALCHEMY"] = db
app.config["SESSION_SQLALCHEMY_TABLE"] = "sessions"

Reading and Setting Cookies Directly

from flask import request, make_response

# Read incoming cookie
theme = request.cookies.get("theme", "light")

# Set a cookie on the response
resp = make_response(render_template("page.html"))
resp.set_cookie(
    "theme",
    value="dark",
    max_age=60 * 60 * 24 * 365,   # 1 year in seconds
    expires=None,                   # datetime or UNIX timestamp (alternative to max_age)
    path="/",
    domain=None,                    # restrict to subdomain: ".example.com"
    secure=True,                    # HTTPS only
    httponly=True,                  # block JS access
    samesite="Lax",                 # "Strict", "Lax", "None"
)
return resp

# Delete a cookie (set expiry in the past)
resp.delete_cookie("theme")
resp.delete_cookie("theme", path="/", domain=".example.com")

max_age vs expires

AttributeTypeNotes
max_ageint (seconds)Relative; preferred — works in all modern browsers
expiresdatetime or intAbsolute UTC datetime; use when you need a specific expiry time

If both are set, max_age takes precedence in most browsers.

Flash Messages (Session-Backed)

Flash messages are stored in the session under "_flashes" and consumed once on the next request.

from flask import flash, get_flashed_messages

# Write (in a view)
flash("Login successful!")
flash("Email is required.", "error")

# Read (in a view or template)
messages = get_flashed_messages()                      # list of strings
messages = get_flashed_messages(with_categories=True)  # list of (category, message)

Default category is "message" when no category is given.

Accessing Session Outside Request Context

# Push an artificial request context (tests / scripts)
with app.test_request_context("/"):
    session["user_id"] = 1
    print(session.get("user_id"))

Common Patterns

Login / Logout

@app.route("/login", methods=["POST"])
def login():
    stmt = select(User).where(User.email == request.form["email"])
    user = db.session.execute(stmt).scalar_one_or_none()
    if user and user.check_password(request.form["password"]):
        session.permanent = True
        session["user_id"] = user.id
        flash("Welcome back!", "success")
        return redirect(request.args.get("next") or url_for("dashboard"))
    flash("Invalid credentials.", "error")
    return redirect(url_for("login"))

@app.route("/logout")
def logout():
    session.clear()
    flash("You have been logged out.")
    return redirect(url_for("index"))

Login-Required Decorator

import functools
from flask import g, redirect, url_for, session

def login_required(f):
    @functools.wraps(f)
    def decorated(*args, **kwargs):
        if "user_id" not in session:
            return redirect(url_for("login", next=request.url))
        return f(*args, **kwargs)
    return decorated

@app.before_request
def load_user():
    user_id = session.get("user_id")
    g.user = db.session.get(User, user_id) if user_id else None

"Remember Me" Cookie (Long-Lived)

@app.route("/login", methods=["POST"])
def login():
    remember = request.form.get("remember") == "on"
    session.permanent = remember
    # PERMANENT_SESSION_LIFETIME controls duration when permanent=True
    session["user_id"] = user.id
    return redirect(url_for("dashboard"))