How to serve static files in Flask


So this is embarrassing. I’ve got an application that I threw together in Flask and for now it is just serving up a single static HTML page with some links to CSS and JS. And I can’t find where in the documentation Flask describes returning static files. Yes, I could use render_template but I know the data is not templatized. I’d have thought send_file or url_for was the right thing, but I could not get those to work. In the meantime, I am opening the files, reading content, and rigging up a Response with appropriate mimetype:

import os.path

from flask import Flask, Response

app = Flask(__name__)

def root_dir():  # pragma: no cover
    return os.path.abspath(os.path.dirname(__file__))

def get_file(filename):  # pragma: no cover
        src = os.path.join(root_dir(), filename)
        # Figure out how flask returns static files
        # Tried:
        # - render_template
        # - send_file
        # This should not be so non-obvious
        return open(src).read()
    except IOError as exc:
        return str(exc)

@app.route('/', methods=['GET'])
def metrics():  # pragma: no cover
    content = get_file('jenkins_analytics.html')
    return Response(content, mimetype="text/html")

@app.route('/', defaults={'path': ''})
def get_resource(path):  # pragma: no cover
    mimetypes = {
        ".css": "text/css",
        ".html": "text/html",
        ".js": "application/javascript",
    complete_path = os.path.join(root_dir(), path)
    ext = os.path.splitext(path)[1]
    mimetype = mimetypes.get(ext, "text/html")
    content = get_file(complete_path)
    return Response(content, mimetype=mimetype)

if __name__ == '__main__':  # pragma: no cover

Someone want to give a code sample or url for this? I know this is going to be dead simple.

Asked By: hughdbrown



I’m sure you’ll find what you need there:

Basically you just need a “static” folder at the root of your package, and then you can use url_for('static', filename='') or directly link to your files with

EDIT: As suggested in the comments you could directly use the '/static/' URL path BUT url_for() overhead (performance wise) is quite low, and using it means that you’ll be able to easily customise the behaviour afterwards (change the folder, change the URL path, move your static files to S3, etc).

Answered By: b4stien

What I use (and it’s been working great) is a “templates” directory and a “static” directory. I place all my .html files/Flask templates inside the templates directory, and static contains CSS/JS. render_template works fine for generic html files to my knowledge, regardless of the extent at which you used Flask’s templating syntax. Below is a sample call in my file.

def projects():
    return render_template("projects.html", title = 'Projects')

Just make sure you use url_for() when you do want to reference some static file in the separate static directory. You’ll probably end up doing this anyways in your CSS/JS file links in html. For instance…

<script src="{{ url_for('static', filename='styles/dist/js/bootstrap.js') }}"></script>

Here’s a link to the “canonical” informal Flask tutorial – lots of great tips in here to help you hit the ground running.

Answered By: Kevin Busch

In production, configure the HTTP server (Nginx, Apache, etc.) in front of your application to serve requests to /static from the static folder. A dedicated web server is very good at serving static files efficiently, although you probably won’t notice a difference compared to Flask at low volumes.

Flask automatically creates a /static/<path:filename> route that will serve any filename under the static folder next to the Python module that defines your Flask app. Use url_for to link to static files: url_for('static', filename='js/analytics.js')

You can also use send_from_directory to serve files from a directory in your own route. This takes a base directory and a path, and ensures that the path is contained in the directory, which makes it safe to accept user-provided paths. This can be useful in cases where you want to check something before serving the file, such as if the logged in user has permission.

from flask import send_from_directory

def send_report(path):
    return send_from_directory('reports', path)

Do not use send_file or send_static_file with a user-supplied path. send_from_directory was designed to safely handle user-supplied paths under a known directory, and will raise an error if the path attempts to escape the directory.

If you are generating a file in memory without writing it to the filesystem, you can pass a BytesIO object to send_file to serve it like a file. You’ll need to pass other arguments to send_file in this case since it can’t infer things like the file name or content type.

Answered By: atupal

   By default, flask use a “templates” folder to contain all your template files(any plain-text file, but usually .html or some kind of template language such as jinja2 ) & a “static” folder to contain all your static files(i.e. .js .css and your images).
   In your routes, u can use render_template() to render a template file (as I say above, by default it is placed in the templates folder) as the response for your request. And in the template file (it’s usually a .html-like file), u may use some .js and/or `.css’ files, so I guess your question is how u link these static files to the current template file.

Answered By: Harvey

A simplest working example based on the other answers is the following:

from flask import Flask, request
app = Flask(__name__, static_url_path='')

def root():
    return app.send_static_file('index.html')

if __name__ == '__main__':

With the HTML called index.html:

<!DOCTYPE html>
    <title>Hello World!</title>
            This is a test.

IMPORTANT: And index.html is in a folder called static, meaning <projectpath> has the .py file, and <projectpath>static has the html file.

If you want the server to be visible on the network, use, host='')

EDIT: For showing all files in the folder if requested, use this

def static_file(path):
    return app.send_static_file(path)

Which is essentially BlackMamba‘s answer, so give them an upvote.

Answered By: EpicPandaForce

You can also, and this is my favorite, set a folder as static path so that the files inside are reachable for everyone.

app = Flask(__name__, static_url_path='/static')

With that set you can use the standard HTML:

<link rel="stylesheet" type="text/css" href="/static/style.css">
Answered By: sharpshadow

For angular+boilerplate flow which creates next folders tree:

|      |------------------build/          <--'static' folder, constructed by Grunt
|      |--<proj           |----vendors/   <-- angular.js and others here
|      |--     folders>   |----src/       <-- your js
|                         |----index.html <-- your SPA entrypoint 
|------     folders>
|  <-- Flask app here

I use following solution:

root = os.path.join(os.path.dirname(os.path.abspath(__file__)), "ui", "build")

@app.route('/<path:path>', methods=['GET'])
def static_proxy(path):
    return send_from_directory(root, path)

@app.route('/', methods=['GET'])
def redirect_to_index():
    return send_from_directory(root, 'index.html')

It helps to redefine ‘static’ folder to custom.

Answered By: kore666

You can use this function :

Function used internally to send static
files from the static folder to the browser.

app = Flask(__name__)
def static_file(path):
    return app.send_static_file(path)
Answered By: BlackMamba

So I got things working (based on @user1671599 answer) and wanted to share it with you guys.

(I hope I’m doing it right since it’s my first app in Python)

I did this –

Project structure:

enter image description here

from server.AppStarter import AppStarter
import os

static_folder_root = os.path.join(os.path.dirname(os.path.abspath(__file__)), "client")

app = AppStarter()

from flask import Flask, send_from_directory
from flask_restful import Api, Resource
from server.ApiResources.TodoList import TodoList
from server.ApiResources.Todo import Todo

class AppStarter(Resource):
    def __init__(self):
        self._static_files_root_folder_path = ''  # Default is current folder
        self._app = Flask(__name__)  # , static_folder='client', static_url_path='')
        self._api = Api(self._app)

    def _register_static_server(self, static_files_root_folder_path):
        self._static_files_root_folder_path = static_files_root_folder_path
        self._app.add_url_rule('/<path:file_relative_path_to_root>', 'serve_page', self._serve_page, methods=['GET'])
        self._app.add_url_rule('/', 'index', self._goto_index, methods=['GET'])

    def register_routes_to_resources(self, static_files_root_folder_path):

        self._api.add_resource(TodoList, '/todos')
        self._api.add_resource(Todo, '/todos/<todo_id>')

    def _goto_index(self):
        return self._serve_page("index.html")

    def _serve_page(self, file_relative_path_to_root):
        return send_from_directory(self._static_files_root_folder_path, file_relative_path_to_root)

    def run(self, module_name):
        if module_name == '__main__':
Answered By: danfromisrael

Use redirect and url_for

from flask import redirect, url_for

@app.route('/', methods=['GET'])
def metrics():
    return redirect(url_for('static', filename='jenkins_analytics.html'))

This servers all files (css & js…) referenced in your html.

Answered By: forzagreen

If you just want to move the location of your static files, then the simplest method is to declare the paths in the constructor. In the example below, I have moved my templates and static files into a sub-folder called web.

app = Flask(__name__,
  • static_url_path='' removes any preceding path from the URL (i.e.
    the default /static).
  • static_folder='web/static' to serve any files found in the folder
    web/static as static files.
  • template_folder='web/templates' similarly, this changes the
    templates folder.

Using this method, the following URL will return a CSS file:

<link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css">

And finally, here’s a snap of the folder structure, where is the Flask instance:

Nested Static Flask Folders

Answered By: Richard Dunn

If you are just trying to open a file, you could use app.open_resource(). So reading a file would look something like

with app.open_resource('/static/path/yourfile'):
      #code to read the file and do something
Answered By: Chaitanya Shivade

Thought of sharing…. this example.

from flask import Flask
app = Flask(__name__)

def hello_world():
    data = open('sample.html').read()    
    return data

if __name__ == '__main__':'')

This works better and simple.

Answered By: Jeevan Chaitanya

One of the simple way to do. Cheers!

from flask import Flask, render_template
app = Flask(__name__)

def index():
   return render_template("index.html")

if __name__ == '__main__': = True)

Now create folder name called templates.
Add your index.html file inside of templates folder


<!DOCTYPE html>
    <title>Python Web Application</title>
            Welcomes You!!

Project Structure
Answered By: Maheshvirus

All the answers are good but what worked well for me is just using the simple function send_file from Flask. This works well when you just need to send an html file as response when host:port/ApiName will show the output of the file in browser

def ApiFunc():
        return send_file('some-other-directory-than-root/your-file.extension')
    except Exception as e:[0])```

Answered By: Binoy S Kumar

The simplest way is create a static folder inside the main project folder. Static folder containing .css files.

main folder

/Main Folder
/Main Folder/templates/foo.html
/Main Folder/static/foo.css
/Main Folder/ script)

Image of main folder containing static and templates folders and flask script


from flask import Flask, render_template

app = Flask(__name__)

def login():
    return render_template("login.html")

html (layout)

<!DOCTYPE html>
        <link rel="stylesheet" href="/static/styles.css">
            <div class="container">
                    <a class="title" href="">Kamook</a>
                    <a class="text" href="">Sign Up</a>
                    <a class="text" href="">Log In</a>
        {% block body %}
        {% endblock %}


{% extends "layout.html" %}

{% block body %}
    <div class="col">
        <input type="text" name="username" placeholder="Username" required>
        <input type="password" name="password" placeholder="Password" required>
        <input type="submit" value="Login">
{% endblock %}
Answered By: ESbros
app = Flask(__name__, static_folder="your path to static")

If you have templates in your root directory, placing the app=Flask(name) will work if the file that contains this also is in the same location, if this file is in another location, you will have to specify the template location to enable Flask to point to the location

Answered By: Novak254

The URL for a static file can be created using the static endpoint as following:

url_for('static', filename = 'name_of_file')
<link rel="stylesheet" href="{{url_for('static', filename='borders.css')}}" />
Answered By: Divyani Singh

By default folder named "static" contains all static files
Here’s code sample:

<link href="{{ url_for('static', filename='vendor/bootstrap/css/bootstrap.min.css') }}" rel="stylesheet">

Answered By: Meenu

In the static directory, create templates directory inside that directory add all the html file create separate directory for css and javascript as flask will treat or recognize all the html files which are inside the template directory.

static -
       |_ templates
       |_ css
Answered By: yuviscor

In my case, i needed all the files from a static folder to be accessible by the user, as well as i needed to use templates for some of my html files, so that common html code could be placed in the template and code gets reused. Here is how i achieved both of them together:

from flask import Flask, request, render_template
from flask.json import JSONEncoder

app = Flask(__name__, template_folder='static')

def serve_static_file(path):
    # In my case, only html files are having the template code inside them, like include.
    if path.endswith('.html'):
        return render_template(path)
    # Serve all other files from the static folder directly.
    return app.send_static_file(path)

And all of my files are kept under static folder, which is parallel to main flask file.

enter image description here

Answered By: Yogesh Kumar Gupta

This is what worked for me:

import os
from flask import Flask, render_template, send_from_directory
app = Flask(__name__)

root = os.path.join(os.path.dirname(os.path.abspath(__file__)), "whereyourfilesare")

@app.route('/', methods=['GET'])
def main(request):
    path = request.path
    if (path == '/'):
        return send_from_directory(root, 'index.html')
        return send_from_directory(root, path[1:])
Answered By: TOBlender

The issue I had was related to index.html files not being served for directories when using static_url_path and static_folder.

Here’s my solution:

import os
from flask import Flask, send_from_directory
from flask.helpers import safe_join

app = Flask(__name__)
static = safe_join(os.path.dirname(__file__), 'static')

def _home():
  return send_from_directory(static, 'index.html')

def _static(path):
  if os.path.isdir(safe_join(static, path)):
    path = os.path.join(path, 'index.html')
  return send_from_directory(static, path)
Answered By: pbatey

For example, to return an Adsense file I have used:

def send_adstxt():
    return send_from_directory(app.static_folder, 'ads.txt')
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.