Flask Cheatsheet

Request Handling

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

The request Object

from flask import request

request is a thread-local proxy — it is only valid inside a view function or a function called from one (or inside a manually pushed request context).

Query String Parameters

# GET /search?q=flask&page=2&tag=python&tag=web
request.args.get("q")                # "flask"
request.args.get("page", 1, type=int)  # 2  (converts, returns default on failure)
request.args.getlist("tag")           # ["python", "web"]
request.args["q"]                     # KeyError if missing — prefer .get()
dict(request.args)                    # {"q": ["flask"], "page": ["2"], ...}

Form Data (POST body)

# application/x-www-form-urlencoded or multipart/form-data
request.form.get("username")
request.form.get("age", type=int)
request.form.getlist("colors")        # multi-select checkbox values
request.form["username"]              # KeyError if missing

JSON Body

# Content-Type: application/json
data = request.get_json()             # dict or None
data = request.get_json(force=True)   # parse even without correct Content-Type
data = request.get_json(silent=True)  # return None on parse error (no 400)

request.json is a shortcut property — raises 400 if body is not valid JSON. Prefer get_json(silent=True) for APIs.

File Uploads

# enctype="multipart/form-data" required in HTML form
file = request.files.get("avatar")
if file and file.filename:
    from werkzeug.utils import secure_filename
    import os
    filename = secure_filename(file.filename)   # sanitize path
    file.save(os.path.join(app.config["UPLOAD_FOLDER"], filename))
    # file.read()  → bytes
    # file.stream → file-like object
    # file.mimetype → "image/png"
    # file.content_length → int or None

Multiple files:

files = request.files.getlist("photos")
for f in files:
    f.save(...)

Request Attributes Quick Reference

AttributeTypeDescription
request.methodstr"GET", "POST", etc.
request.urlstrFull URL including query string
request.base_urlstrURL without query string
request.hoststrhost:port
request.host_urlstrscheme://host/
request.root_urlstrscheme://host/app_root/
request.pathstrPath only, no query string
request.full_pathstrPath + query string
request.script_rootstrWSGI SCRIPT_NAME prefix
request.endpointstrMatched endpoint name
request.view_argsdictURL variable values
request.argsImmutableMultiDictQuery string params
request.formImmutableMultiDictForm body params
request.filesImmutableMultiDictUploaded files
request.jsonAnyParsed JSON body
request.databytesRaw request body
request.headersHeadersRequest headers (case-insensitive)
request.cookiesdictIncoming cookies
request.environdictRaw WSGI environ
request.remote_addrstrClient IP (may be proxy IP)
request.referrerstr | NoneReferer header
request.user_agentUserAgentParsed User-Agent
request.content_typestrContent-Type without params
request.content_lengthint | NoneBody size in bytes
request.is_jsonboolTrue if JSON content type
request.is_secureboolTrue if HTTPS
request.is_xhrboolTrue if X-Requested-With: XMLHttpRequest

Headers

request.headers["Authorization"]          # KeyError if missing
request.headers.get("X-Api-Key")          # None if missing
request.headers.get("Content-Type")       # case-insensitive lookup
dict(request.headers)                     # all headers as dict

Cookies

request.cookies.get("session_id")
request.cookies["theme"]                  # KeyError if missing

Raw Body

request.data           # bytes; only populated if not form/files
request.get_data()     # bytes; always reads body
request.get_data(cache=False)  # don't cache body (saves memory for large bodies)
request.stream         # file-like, for streaming uploads

Request Context Locals

from flask import g

# g is per-request storage, cleared after each request
g.user = load_user_from_db()
g.db = get_db_connection()
g.get("user", None)    # safe access with default

Accessing Request Outside View

Push a context manually for scripts/tests:

with app.test_request_context("/search?q=flask", method="GET"):
    print(request.args["q"])   # "flask"

Content Negotiation

request.accept_mimetypes.best_match(["application/json", "text/html"])
# returns "application/json" or "text/html" based on Accept header

request.accept_languages.best_match(["en", "fr"])

Trusted Proxies (ProxyFix)

When running behind a reverse proxy (nginx, load balancer):

from werkzeug.middleware.proxy_fix import ProxyFix

app.wsgi_app = ProxyFix(
    app.wsgi_app,
    x_for=1,     # X-Forwarded-For hops to trust
    x_proto=1,   # X-Forwarded-Proto
    x_host=1,    # X-Forwarded-Host
    x_prefix=1,  # X-Forwarded-Prefix
)
# Now request.remote_addr and request.is_secure are correct

Without ProxyFix, request.remote_addr returns the proxy's IP and request.is_secure is always False behind HTTPS proxies.