Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/pallets/flask/llms.txt

Use this file to discover all available pages before exploring further.

Flask’s URL routing system maps URL patterns to view functions. The routing rules are managed by Werkzeug’s routing system.

Adding URL Rules

route

Decorator to register a view function for a given URL rule.
@app.route("/")
def index():
    return "Hello, World!"

Signature

def route(rule: str, **options: Any) -> Callable[[T_route], T_route]
rule
str
required
The URL rule string. Can include variable parts in angle brackets, e.g., /user/<username>.
methods
list[str]
List of HTTP methods this route should accept. Defaults to ["GET"]. HEAD and OPTIONS are added automatically.
@app.route("/login", methods=["GET", "POST"])
def login():
    if request.method == "POST":
        # Handle login
        pass
    return render_template("login.html")
endpoint
str
The endpoint name for this route. Defaults to the name of the view function. Used with url_for() to generate URLs.
@app.route("/", endpoint="home")
def index():
    return "Home"

# Later: url_for("home") returns "/"
options
Any
Additional options are passed to the underlying werkzeug.routing.Rule object. Common options include:
  • defaults: Dictionary of default values for URL variables
  • subdomain: Match a specific subdomain
  • strict_slashes: Whether to redirect trailing slashes (default: True)
  • host: Match a specific host
Returns: The decorated view function, unchanged.

add_url_rule

Register a URL rule without using a decorator. Equivalent to using @app.route().
def index():
    return "Hello, World!"

app.add_url_rule("/", view_func=index)

Signature

def add_url_rule(
    rule: str,
    endpoint: str | None = None,
    view_func: RouteCallable | None = None,
    provide_automatic_options: bool | None = None,
    **options: Any,
) -> None
rule
str
required
The URL rule string.
endpoint
str | None
default:"None"
The endpoint name to associate with the rule and view function. Used when routing and building URLs. Defaults to view_func.__name__.
view_func
RouteCallable | None
default:"None"
The view function to associate with the endpoint name. Can be None if you register the function later with the @app.endpoint() decorator.
provide_automatic_options
bool | None
default:"None"
Add the OPTIONS method and respond to OPTIONS requests automatically. Defaults to True.
options
Any
Extra options passed to the werkzeug.routing.Rule object.
Returns: None Raises: AssertionError if a view function is already registered for the endpoint.

endpoint

Decorator to register a view function for a given endpoint. Used if a rule is added without a view_func with add_url_rule().
app.add_url_rule("/ex", endpoint="example")

@app.endpoint("example")
def example():
    return "Example"

Signature

def endpoint(endpoint: str) -> Callable[[F], F]
endpoint
str
required
The endpoint name to associate with the view function.

URL Variables

URL rules can contain variable parts enclosed in angle brackets. The variable is passed as a keyword argument to the view function.
@app.route("/user/<username>")
def show_user(username):
    return f"User: {username}"

Type Converters

Converters can be used to specify the type of the variable:
@app.route("/post/<int:post_id>")
def show_post(post_id):
    # post_id is an integer
    return f"Post {post_id}"
Built-in converters:
  • string - (default) accepts any text without a slash
  • int - accepts positive integers
  • float - accepts positive floating point values
  • path - like string but also accepts slashes
  • uuid - accepts UUID strings

Multiple Variables

@app.route("/post/<int:year>/<int:month>/<int:day>")
def show_post(year, month, day):
    return f"Post from {year}-{month}-{day}"

URL Building

Use url_for() to build URLs for endpoints:
from flask import url_for

@app.route("/")
def index():
    return "Index"

@app.route("/user/<username>")
def profile(username):
    return f"Profile: {username}"

# Build URLs
with app.test_request_context():
    print(url_for("index"))  # /
    print(url_for("profile", username="john"))  # /user/john
    print(url_for("profile", username="john", page=2))  # /user/john?page=2

HTTP Methods

By default, routes only respond to GET requests. Use the methods parameter to handle other HTTP methods:
from flask import request

@app.route("/login", methods=["GET", "POST"])
def login():
    if request.method == "POST":
        # Process login
        return redirect(url_for("index"))
    # Show login form
    return render_template("login.html")
Alternatively, you can use method-specific decorators:
@app.get("/login")
def login_form():
    return render_template("login.html")

@app.post("/login")
def login_submit():
    # Process login
    return redirect(url_for("index"))
Available method decorators:
  • @app.get(rule)
  • @app.post(rule)
  • @app.put(rule)
  • @app.delete(rule)
  • @app.patch(rule)

URL Rule Options

defaults

Provide default values for URL variables:
@app.route("/users/", defaults={"page": 1})
@app.route("/users/page/<int:page>")
def show_users(page):
    return f"Page {page}"

strict_slashes

Control whether trailing slashes are enforced:
# With strict_slashes=True (default):
# /about/ and /about are different URLs

# With strict_slashes=False:
@app.route("/about", strict_slashes=False)
def about():
    return "About"  # Matches both /about and /about/

subdomain

Match specific subdomains:
@app.route("/", subdomain="api")
def api_index():
    return "API"  # Matches api.example.com/
Requires setting SERVER_NAME in the config.

host

Match specific hosts:
@app.route("/", host="api.example.com")
def api():
    return "API"

Rule Object

When you call add_url_rule(), Flask creates a werkzeug.routing.Rule object. This object contains:
  • rule: The URL rule string
  • methods: Set of HTTP methods
  • endpoint: The endpoint name
  • defaults: Default values for variables
  • subdomain: Subdomain pattern
  • host: Host pattern
  • strict_slashes: Whether trailing slashes matter
  • provide_automatic_options: Whether OPTIONS is handled automatically
You can access registered rules via app.url_map:
for rule in app.url_map.iter_rules():
    print(rule.endpoint, rule.rule, rule.methods)

Examples

REST API Routes

@app.route("/api/users", methods=["GET"])
def list_users():
    return jsonify({"users": []})

@app.route("/api/users", methods=["POST"])
def create_user():
    data = request.get_json()
    return jsonify(data), 201

@app.route("/api/users/<int:user_id>", methods=["GET"])
def get_user(user_id):
    return jsonify({"id": user_id})

@app.route("/api/users/<int:user_id>", methods=["PUT"])
def update_user(user_id):
    data = request.get_json()
    return jsonify(data)

@app.route("/api/users/<int:user_id>", methods=["DELETE"])
def delete_user(user_id):
    return "", 204

Multiple URL Patterns for One View

@app.route("/")
@app.route("/index")
@app.route("/home")
def index():
    return "Home page"

URL Patterns with Optional Parts

@app.route("/posts/")
@app.route("/posts/<int:post_id>")
def posts(post_id=None):
    if post_id is None:
        return "All posts"
    return f"Post {post_id}"

See Also