Dynamic Routes & Variables

A dynamic route is a route with a variable part in its URL, written in angle brackets like /user/<name> — the value in that spot is captured from the URL and passed straight into your view function.

Learn Dynamic Routes & Variables in our free Flask course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick…

Part of the free Flask course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

In this lesson you'll capture values from URLs, use converters to control their type, and build flexible pages that respond to many addresses with a single function. Run any example locally with flask run .

What You'll Learn in This Lesson

1 Capturing a Value From the URL

A dynamic route has a piece of its path wrapped in angle brackets . The text inside the brackets is a variable name . When a request matches, Flask pulls that part of the URL out and passes it to your view function as an argument with the same name.

In the example below, visiting /user/Ada calls profile(username="Ada") . The same single function handles /user/Grace , /user/Linus , and any other name.

2 Converters: Controlling the Type

By default a captured value is a string . A converter lets you require a specific type by writing it before the variable name, like <int:post_id> . Flask both checks the value matches and converts it for you — so post_id arrives as a real Python int .

If the URL doesn't match the converter (for example /post/hello when an int is expected), Flask returns a 404 instead of calling your function.

3 Multiple Variables in One Route

A route can capture more than one value. Each angle-bracket section becomes one argument, in order. The route below captures a category as text and an item id as an integer.

The order matters: the first bracket maps to the first parameter, the second bracket to the second. The names just need to match between the route and the function signature.

🔬 Anatomy of a Dynamic Route

Pattern

What it captures

/user/<name>

Any text as a string, passed as name

/post/<int:id>

A whole number, passed as an int

/price/<float:amt>

A decimal, passed as a float

/files/<path:p>

Text that may contain slashes

🎯 Your Turn: Fill in the Blanks

Finish a route that greets a user by name and another that shows a numbered order. Replace each ___ .

Common Errors & Quick Reference

❌ TypeError: profile() missing 1 required positional argument

Your view function takes a parameter but you forgot the matching variable in the route, or the names don't match. The bracket name and the parameter name must be identical.

The converter rejected the value. <int:post_id> only matches numbers, so a non-numeric value never reaches your function — that's working as intended.

Goal

Route pattern

Capture text

Capture an integer

Capture a decimal

Capture a path

🏆 Mini Challenge: A Blog URL Scheme

❓ Frequently Asked Questions

Lesson 3 complete — your routes are dynamic now!

You can capture values from URLs, convert them with <int:...> and friends, and handle several variables in one route. One function can now serve thousands of URLs.

🚀 Up next: HTTP Methods (GET & POST) — handle form submissions and learn the difference between reading and sending data.

Practice quiz

How do you mark a variable part of a URL in a Flask route?

  • with curly braces {name}
  • with angle brackets <name>
  • with a colon :name
  • with parentheses (name)

Answer: with angle brackets <name>. Angle brackets like /user/<name> capture that part of the URL.

In @app.route('/user/<username>'), how is the value passed to the view?

  • as a function argument named username
  • via request.args
  • in a global variable
  • username

Answer: as a function argument named username. The captured segment is passed as the matching function parameter.

What type does a captured value have by default (no converter)?

  • int
  • bytes
  • string
  • list

Answer: string. Without a converter, captured URL values are strings.

Which converter requires a whole number and passes it as an int?

  • <num:id>
  • <digit:id>
  • <integer:id>
  • <int:id>

Answer: <int:id>. <int:id> matches whole numbers and converts the value to a Python int.

What happens when /post/abc hits a route declared as /post/<int:id>?

  • Flask returns a 404 Not Found
  • id becomes the string 'abc'
  • Flask raises a 500 error
  • id becomes 0

Answer: Flask returns a 404 Not Found. A non-integer does not match the converter, so the route is not selected and Flask returns 404.

Which converter matches text that may contain slashes?

  • <slash:p>
  • <path:p>
  • <any:p>
  • <url:p>

Answer: <path:p>. <path:p> accepts segments that include forward slashes.

Which converter is used for a decimal number?

  • <decimal:x>
  • <double:x>
  • <float:x>
  • <number:x>

Answer: <float:x>. <float:x> matches a decimal and passes it as a Python float.

Can a single route capture more than one variable?

  • Yes — each angle-bracket section is one argument
  • No, only one is allowed
  • Only with query strings
  • Only if both are ints

Answer: Yes — each angle-bracket section is one argument. A route like /<category>/<int:item_id> maps each bracket to a parameter in order.

For /shop/<category>/<int:item_id>, how does the view receive them?

  • both as strings
  • as request.args
  • as two parameters: category (str) and item_id (int)
  • as a single dict

Answer: as two parameters: category (str) and item_id (int). Each bracket becomes a parameter; the int converter makes item_id an int.

What must match between the route bracket and the view function?

  • the file name
  • the HTTP method
  • the return type
  • the variable/parameter name

Answer: the variable/parameter name. <username> in the route must pair with a username parameter in the function.

Continue this course