Sessions & Cookies
Reviewed & published by Brayan K
A session is a per-user store that remembers data across requests, and a cookie is the small piece of browser-stored data Flask uses to make that possible — together they're how a site keeps you logged in.
Part of the free Flask course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.
In this lesson you'll store data in the session object, read it back on later requests, set your own cookies directly, and understand why a secret_key is essential.
What You'll Learn in This Lesson
- What sessions and cookies are and how they relate
- Why session needs a secret_key to stay secure
- Storing and reading values with the session object
- Clearing session data to log a user out
- Setting cookies directly with set_cookie
- Reading cookies back with request.cookies
1 Storing Data in the Session
HTTP is stateless — each request arrives with no memory of the last one. The session object fixes that. It behaves like a dictionary you can write to in one request and read from in the next, scoped to a single user.
Because Flask stores the session in a signed cookie, you must set app.secret_key so users can't tamper with it. The example below logs a user in by saving their name to the session, then reads it back on the home page.
# app.py — remember a user with the session object
from flask import Flask, session, redirect, url_for
app = Flask(__name__)
app.secret_key = "change-me-in-production" # signs the session cookie
@app.route("/login/<username>")
def login(username):
# Write to the session like a dictionary
session["user"] = username
return redirect(url_for("home"))
@app.route("/")
def home():
# Read it back on a later request
user = session.get("user")
if user:
return f"Logged in as {user}."
return "You are not logged in."
# The test client keeps cookies between requests, like a browser:
with app.test_client() as client:
print(client.get("/").data.decode()) # You are not logged in.
client.get("/login/ada") # stores user in session
print(client.get("/").data.decode()) # Logged in as ada.
# ✅ Expected output:
# You are not logged in.
# Logged in as ada.On the first request there's no session, so you see "You are not logged in." After visiting the login route, the session remembers the user and the home page greets them by name.
2 Logging Out: Clearing the Session
Logging a user out means removing their data from the session. Use session.pop("key", None) to drop a single value, or session.clear() to wipe everything.
The example below adds a logout route that clears the stored user and redirects home. After logout, the home page reports that nobody is signed in.
# app.py — log a user out by clearing the session
from flask import Flask, session, redirect, url_for
app = Flask(__name__)
app.secret_key = "dev-secret"
@app.route("/login/<username>")
def login(username):
session["user"] = username
return redirect(url_for("home"))
@app.route("/logout")
def logout():
session.pop("user", None) # remove just the user; session.clear() wipes all
return redirect(url_for("home"))
@app.route("/")
def home():
user = session.get("user")
return f"Hello, {user}!" if user else "Nobody is logged in."
with app.test_client() as client:
client.get("/login/grace")
print(client.get("/").data.decode()) # Hello, grace!
client.get("/logout")
print(client.get("/").data.decode()) # Nobody is logged in.
# ✅ Expected output:
# Hello, grace!
# Nobody is logged in.3 Setting Cookies Directly
Sometimes you want a plain cookie rather than the session — for example to remember a theme preference. Build a response with make_response(...), call response.set_cookie(name, value), and read it later with request.cookies.get(name).
The example below stores a theme cookie on one route and reads it back on another, returning the saved theme or a default.
# app.py — set and read a cookie directly
from flask import Flask, request, make_response
app = Flask(__name__)
@app.route("/set-theme/<theme>")
def set_theme(theme):
response = make_response(f"Theme set to {theme}.")
# Store a cookie in the browser for one week (max_age in seconds)
response.set_cookie("theme", theme, max_age=60 * 60 * 24 * 7)
return response
@app.route("/theme")
def show_theme():
# Read the cookie back; default to 'light' if it's not set
theme = request.cookies.get("theme", "light")
return f"Current theme: {theme}"
with app.test_client() as client:
print(client.get("/theme").data.decode()) # Current theme: light
client.get("/set-theme/dark") # stores the cookie
print(client.get("/theme").data.decode()) # Current theme: dark
# ✅ Expected output:
# Current theme: light
# Current theme: dark🔬 Sessions vs Cookies at a Glance
| Task | Code |
|---|---|
| Save to session | session["user"] = name |
| Read from session | session.get("user") |
| Log out | session.pop("user", None) |
| Set a cookie | response.set_cookie("theme", "dark") |
| Read a cookie | request.cookies.get("theme") |
🎯 Your Turn: Fill in the Blanks
Complete the visit counter below. Replace each ___ so it stores a count in the session and increments it on each request.
# 🎯 YOUR TURN: replace each ___ to build a visit counter
from flask import Flask, session
app = Flask(__name__)
app.___ = "dev-key" # what attribute signs the session cookie?
@app.route("/")
def counter():
# Read the current count, defaulting to 0
count = session.___("count", 0) # which method reads with a default?
count += 1
session["count"] = count # store the new count back in the session
return f"You have visited {count} time(s)."
with app.test_client() as client:
print(client.get("/").data.decode()) # ...1 time(s)
print(client.get("/").data.decode()) # ...2 time(s)Common Errors & Quick Reference
❌ RuntimeError: The session is unavailable because no secret key was set
You used session without a key. Set app.secret_key = "..." once after creating the app. Use a long, random value in production.
❌ My cookie or session "doesn't stick" between requests
Cookies are tied to the browser. Tools like curl drop them unless you tell them to persist. In tests, reuse one app.test_client() so cookies carry over like a real browser.
| Task | Code |
|---|---|
| Enable sessions | app.secret_key = "..." |
| Store a value | session["key"] = value |
| Clear everything | session.clear() |
| Run the app | flask run |
🏆 Mini Challenge: A Login Gate
Build a protected page that only logged-in users can see.
- Store the username in the session on login
- On /secret, check the session for a user
- Show the secret if logged in, otherwise redirect to login
# 🏆 Mini Challenge: a login-gated page
from flask import Flask, session, redirect, url_for
app = Flask(__name__)
app.secret_key = "dev-secret"
@app.route("/login/<username>")
def login(username):
session["user"] = username
return redirect(url_for("secret"))
@app.route("/secret")
def secret():
if "user" not in session:
return redirect(url_for("login", username="guest"))
return f"Top secret data for {session['user']}!"
with app.test_client() as client:
# Not logged in -> redirected to login, which logs in 'guest'
print(client.get("/secret", follow_redirects=True).data.decode())
client.get("/login/ada")
print(client.get("/secret").data.decode()) # Top secret data for ada!❓ Frequently Asked Questions
Lesson complete — your app can remember its users!
You stored and cleared data in the session, set and read raw cookies, and learned why app.secret_key keeps sessions safe.
Practice quiz
How does the Flask session object behave in your code?
- Like a file handle
- Like a dictionary
- Like a database cursor
- Like a list
Answer: Like a dictionary. session behaves like a dictionary you read from and write to.
Where does Flask store the session data by default?
- In a server-side file
- In the URL
- In a signed cookie
- In a database table
Answer: In a signed cookie. Flask serializes the session into a signed cookie sent to the browser.
What must you set for sessions to work?
- app.debug
- app.config['DB']
- app.name
- app.secret_key
Answer: app.secret_key. app.secret_key signs the session cookie; without it session use raises an error.
How do you safely read a session value with a default?
- session.get("user")
- session.read("user")
- session.fetch("user")
- session.value("user")
Answer: session.get("user"). session.get("user") returns the value or None/default if absent.
How do you remove a single value to log a user out?
- session.delete("user")
- session.pop("user", None)
- session.remove("user")
- del session
Answer: session.pop("user", None). session.pop("user", None) removes just that key.
Which call wipes everything from the session?
- session.reset()
- session.empty()
- session.clear()
- session.drop()
Answer: session.clear(). session.clear() removes all stored session data.
How do you set a cookie directly on a response?
- request.set_cookie(...)
- cookie.add(...)
- session.cookie(...)
- response.set_cookie(name, value)
Answer: response.set_cookie(name, value). Build a response with make_response and call response.set_cookie(name, value).
How do you read a cookie the browser sent back?
- request.cookies.get("theme")
- session.cookie("theme")
- response.cookies["theme"]
- request.form.get("theme")
Answer: request.cookies.get("theme"). request.cookies.get("theme") reads an incoming cookie value.
Why does Flask sign the session cookie?
- To compress it
- So users can't tamper with its contents
- To encrypt the database
- To speed up requests
Answer: So users can't tamper with its contents. Signing lets Flask detect tampering with the cookie's contents.
What property of HTTP makes sessions necessary?
- It is encrypted
- It only supports GET
- It is stateless — each request has no memory of the last
- It caches everything
Answer: It is stateless — each request has no memory of the last. HTTP is stateless, so sessions add per-user memory across requests.
Continue this course
- Previous: Handling Forms
- Next: Flask Blueprints — Split a growing app into modular, reusable components
- Quick reference: Flask cheat sheet › Forms & Sessions
Frequently asked questions
What is a session in Flask?
A session is a per-user store that persists across requests. Flask's session object behaves like a dictionary; you read and write keys, and Flask saves the data in a signed cookie so the same user sees it on their next request.
What is the difference between a session and a cookie?
A cookie is a small piece of data stored in the browser and sent back with every request. Flask's session is built on a single signed cookie: you work with a dictionary in Python, and Flask handles writing and reading the cookie for you.
Why does session require a secret_key?
Flask signs the session cookie with app.secret_key so users can't tamper with its contents. Without a secret key, any attempt to use session raises an error. Use a long, random value and keep it out of source control in production.
How do I set my own cookie directly?
Build a response with make_response(...) and call response.set_cookie('name', 'value'). The browser stores it and sends it back; you read it later with request.cookies.get('name'). Sessions are easier for most cases, but raw cookies give you full control.