I have a complex Flask-based web app. There are lots of separate files with view functions. Their URLs are defined with the @app.route('/...')
decorator. Is there a way to get a list of all the routes that have been declared throughout my app? Perhaps there is some method I can call on the app
object?
11 Answers
All the routes for an application are stored on app.url_map
which is an instance of werkzeug.routing.Map
. You can iterate over the Rule
instances by using the iter_rules
method:
from flask import Flask, url_for
app = Flask(__name__)
def has_no_empty_params(rule):
defaults = rule.defaults if rule.defaults is not None else ()
arguments = rule.arguments if rule.arguments is not None else ()
return len(defaults) >= len(arguments)
@app.route("/site-map")
def site_map():
links = []
for rule in app.url_map.iter_rules():
# Filter out rules we can't navigate to in a browser
# and rules that require parameters
if "GET" in rule.methods and has_no_empty_params(rule):
url = url_for(rule.endpoint, **(rule.defaults or {}))
links.append((url, rule.endpoint))
# links is now a list of url, endpoint tuples
See Display links to new webpages created for a bit more information.

- 1
- 1

- 155,703
- 32
- 311
- 293
-
Sweet! Except I had an issue with the line `url = url_for(rule.endpoint)`. I just got this error `BuildError: ('DeleteEvent', {}, None)`. Instead, to get the url I just did `url = rule.rule`. Any idea why your method doesn't work for me? – J-bob Nov 11 '12 at 19:57
-
@J-bob - most likely the route associated with `DeleteEvent` has a *required* parameter - you can either special-case that one or filter out any rules where `len(rule.arguments) > len(rule.defaults)` – Sean Vieira Nov 11 '12 at 22:59
-
Oh I think I get it. `url_for` can't generate the URL for that methid without a parameter, right? OK, but it looks like my method works anyway, it just keeps that portion if the URL as a parameter. Thanks! – J-bob Nov 12 '12 at 02:34
-
This is helpful! You can do a simple check by invoking `python` REPL environment, loading your main flask application, e.g, `import main` and directly displaying its url_map, `main.app.url_map`. It'll gives you list of all defined routes – swdev Mar 17 '14 at 22:53
-
1This is a great start. Any suggestions for how to create a fully self-documenting flask-based web service, where all of the parameters (such as ?spam="eggs") are listed? Perhaps this info can be extracted from a docstring of an implementing method. – Leonid Aug 10 '14 at 04:44
-
3Instead of use `url_for(rule.endpoint)` use `rule.rule` that is much better beacause solve cases where you have more than one route for the same method. – Zini Jul 10 '15 at 14:39
-
Ty for `rule.endpoint` !!!!!!! – Milovan Tomašević Oct 28 '21 at 15:01
I just met the same question. Those solutions above are too complex. Just open a new shell under your project:
>>> from app import app
>>> app.url_map
The first 'app' is my project script: app.py, another is my web's name.
(this solution is for the tiny web with a little route)
-
1This probably does not answer the question directly. But it sure deserves many more upvotes. – UltraInstinct Mar 29 '17 at 23:28
-
This answer is great for not requiring you to add any code to your application. I used it to get the answer I wanted in seconds without rebuilding my code. – joshdick Aug 09 '18 at 15:19
-
" Is there a way to get a list of all the routes that have been declared throughout my app?" I think this answers the question directly and should be the accepted answer. So easy. Thanks. – andho Sep 08 '18 at 05:31
-
3I don't really see how this any simpler or clearer than the accepted answer. It's suggesting the same approach, but takes longer to get to the point and doesn't show how to iterate over the `Map` instance or access any of the properties of the `Rule`s it contains, without which you can't actually do anything useful. – Mark Amery Nov 30 '18 at 18:38
I make a helper method on my manage.py
:
@manager.command
def list_routes():
import urllib
output = []
for rule in app.url_map.iter_rules():
options = {}
for arg in rule.arguments:
options[arg] = "[{0}]".format(arg)
methods = ','.join(rule.methods)
url = url_for(rule.endpoint, **options)
line = urllib.unquote("{:50s} {:20s} {}".format(rule.endpoint, methods, url))
output.append(line)
for line in sorted(output):
print line
It solves the the missing argument by building a dummy set of options. The output looks like:
CampaignView:edit HEAD,OPTIONS,GET /account/[account_id]/campaigns/[campaign_id]/edit
CampaignView:get HEAD,OPTIONS,GET /account/[account_id]/campaign/[campaign_id]
CampaignView:new HEAD,OPTIONS,GET /account/[account_id]/new
Then to run it:
python manage.py list_routes
For more on manage.py checkout: http://flask-script.readthedocs.org/en/latest/

- 16,077
- 12
- 67
- 106
-
7The above works very well. Just change `urllib.unquote` to `urllib.parse.unquote` and `print line` to `print(line)` and it works in python 3.x as well. – squeegee Oct 03 '13 at 19:01
-
2This doesn't work for non-string arguments, I recommend to use John Jiang's answer instead. – nico Jul 05 '18 at 19:25
Apparently, since version 0.11, Flask has a built-in CLI. One of the built-in commands lists the routes:
FLASK_APP='my_project.app' flask routes

- 5,572
- 2
- 32
- 38
-
2`flask urls` for me (0.12.1). Saw that in `flask --help` but I don't see routes or urls on the CLI page – mrgnw May 20 '19 at 17:39
-
-
1@JerryJi That does not look right. `routes` is still there in 1.1.2 – Phil Cooper Aug 11 '21 at 15:08
Similar to Jonathan's answer I opted to do this instead. I don't see the point of using url_for as it will break if your arguments are not string e.g. float
@manager.command
def list_routes():
import urllib
output = []
for rule in app.url_map.iter_rules():
methods = ','.join(rule.methods)
line = urllib.unquote("{:50s} {:20s} {}".format(rule.endpoint, methods, rule))
output.append(line)
for line in sorted(output):
print(line)

- 11,069
- 12
- 51
- 60
Since you did not specify that it has to be run command-line, the following could easily be returned in json for a dashboard or other non-command-line interface. The result and the output really shouldn't be commingled from a design perspective anyhow. It's bad program design, even if it is a tiny program. The result below could then be used in a web application, command-line, or anything else that ingests json.
You also didn't specify that you needed to know the python function associated with each route, so this more precisely answers your original question.
I use below to add the output to a monitoring dashboard myself. If you want the available route methods (GET, POST, PUT, etc.), you would need to combine it with other answers above.
Rule's repr() takes care of converting the required arguments in the route.
def list_routes():
routes = []
for rule in app.url_map.iter_rules():
routes.append('%s' % rule)
return routes
The same thing using a list comprehension:
def list_routes():
return ['%s' % rule for rule in app.url_map.iter_rules()]
Sample output:
{
"routes": [
"/endpoint1",
"/nested/service/endpoint2",
"/favicon.ico",
"/static/<path:filename>"
]
}

- 99
- 1
- 2
-
`TypeError: The view function did not return a valid response. The return type must be a string, dict, tuple, Response instance, or WSGI callable, but it was a list.` – Spooky Apr 26 '21 at 00:04
-
`return "\n
\n".join(map(escape, app.url_map.iter_rules()))` for a plain HTML. – Lenormju Jun 15 '22 at 15:39
If you need to access the view functions themselves, then instead of app.url_map
, use app.view_functions
.
Example script:
from flask import Flask
app = Flask(__name__)
@app.route('/foo/bar')
def route1():
pass
@app.route('/qux/baz')
def route2():
pass
for name, func in app.view_functions.items():
print(name)
print(func)
print()
Output from running the script above:
static
<bound method _PackageBoundObject.send_static_file of <Flask '__main__'>>
route1
<function route1 at 0x128f1b9d8>
route2
<function route2 at 0x128f1ba60>
(Note the inclusion of the "static" route, which is created automatically by Flask.)

- 143,130
- 81
- 406
- 459
You can view all the Routes via flask shell by running the following commands after exporting or setting FLASK_APP environment variable.
flask shell
app.url_map

- 321
- 3
- 8
inside your flask app do:
flask shell
>>> app.url_map
Map([<Rule '/' (OPTIONS, HEAD, GET) -> helloworld>,
<Rule '/static/<filename>' (OPTIONS, HEAD, GET) -> static>])

- 61
- 2
print(app.url_map)
That, is, if your Flask application name is 'app'.
It's an attribute of the instance of the Flask App.
See https://flask.palletsprojects.com/en/2.1.x/api/#flask.Flask.url_map

- 3,288
- 1
- 18
- 15