URL Building & Redirects with url_for

url_for is a Flask function that builds the correct URL for a view by its name, so you never hardcode a path again.

Learn URL Building & Redirects with url_for in our free Flask course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a…

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 generate links from view names, attach query parameters, reference static files, and send the browser elsewhere with redirect .

url_for("view_name") asks Flask for the URL registered to a view function and returns it as a string. You pass the function's name (its endpoint ), and any route parameters as keyword arguments.

Because url_for needs to know about the request, we run it inside test_request_context() — a helper that fakes a request so the example works with no server running. In a real view, the context already exists.

Any keyword you pass that is not a route parameter becomes a query-string value. So url_for("search", q="flask", page=2) appends ?q=flask&page=2 automatically.

The built-in static endpoint generates URLs for your assets: url_for("static", filename="style.css") returns /static/style.css . If you hardcoded /static/... and later moved the folder or added a CDN prefix, every link would break — url_for stays correct.

In a Jinja template you'd write the same call: . That keeps your HTML links in sync with your routes.

redirect(target) tells the browser to go to another URL by sending a 302 response with a Location header. The idiomatic pattern is redirect(url_for("some_view")) so the destination is built from a name, not a hardcoded path.

This is the backbone of the Post/Redirect/Get pattern: after handling a form POST, you redirect to a result page so a browser refresh doesn't resubmit the form.

The status code 302 plus the Location: /user/ada header is exactly what a real browser receives — then it automatically requests that new URL.

Complete the code so it builds a profile URL, a search URL with a query, and a redirect. Replace each ___ .

❌ BuildError: Could not build url for endpoint

The endpoint name is wrong, or you forgot a required route parameter. Pass the exact view function name and every it declares, e.g. url_for("profile", username="ada") .

Calling url_for at import time fails because there's no request. Call it inside a view, a template, or a test_request_context() / app_context() block.

Build a route that redirects a short code to a full article URL.

Lesson complete — your links will never go stale!

You can build URLs from view names, attach query parameters, reference static files, and redirect cleanly with redirect(url_for(...)) .

🚀 Up next: Working with Cookies — store small pieces of data in the browser between requests.

Practice quiz

What does url_for build a URL from?

  • A hardcoded path string
  • The current request URL
  • A regex pattern
  • A view's endpoint name

Answer: A view's endpoint name. url_for('profile') looks up the route registered for that view's endpoint and returns its path.

What does url_for('profile', username='ada') produce for /user/<username>?

  • /profile?username=ada
  • /user/ada
  • /user/<username>
  • /ada

Answer: /user/ada. The keyword matches the route parameter, filling the dynamic segment to give /user/ada.

How does url_for handle a keyword that is NOT a route parameter?

  • It appends it as a query string
  • It raises an error
  • It ignores it
  • It adds it to the path

Answer: It appends it as a query string. Extra keywords become a query string, so url_for('search', q='flask', page=2) gives /search?q=flask&page=2.

Which endpoint name links static files?

  • files
  • assets
  • static
  • public

Answer: static. url_for('static', filename='css/style.css') uses the built-in 'static' endpoint to return /static/css/style.css.

Which idiomatic call redirects to a named view?

  • go(url_for('home'))
  • redirect('/home')
  • send(url_for('home'))
  • redirect(url_for('home'))

Answer: redirect(url_for('home')). redirect(url_for('view')) builds the destination from a name rather than a hardcoded path.

What HTTP status code does redirect() send by default?

  • 200
  • 302
  • 404
  • 500

Answer: 302. redirect() returns a 302 response with a Location header pointing at the target URL.

Why avoid hardcoding URLs like '/user/ada'?

  • They break when you rename a route or add a prefix
  • They load more slowly
  • They are not valid HTML
  • They disable caching

Answer: They break when you rename a route or add a prefix. Hardcoded strings break when the URL map changes; url_for asks Flask for the current path.

Why must url_for run inside a request or test_request_context()?

  • To compress the URL
  • Because it needs an active request context
  • To enable CSRF
  • To cache the result

Answer: Because it needs an active request context. Calling url_for at import time fails; it needs a view, a template, or a test_request_context() block.

Which header carries the destination of a 302 redirect?

  • Refresh
  • Redirect
  • Location
  • Forward

Answer: Location. A redirect sets the Location header, which the browser then follows to the new URL.

What raises a BuildError from url_for?

  • Passing too many query params
  • Using it inside a template
  • Calling redirect first
  • A wrong endpoint name or a missing route parameter

Answer: A wrong endpoint name or a missing route parameter. BuildError means the endpoint name is wrong or a required <param> was not supplied.