Favicon ToolsVerifyBuild
Framework

Django Favicon Generator

Django does not special-case favicons. Icons are ordinary static files collected into STATIC_ROOT and referenced from your base template with the static template tag. In production the collectstatic step is what makes them reachable.

Static files, not media

Favicons belong with CSS and JS under the static files system, not under MEDIA_ROOT. MEDIA_ROOT is for user uploads. Icons are part of the project, so they live in an app's static/ directory or in a project-level directory listed in STATICFILES_DIRS.

In development, django.contrib.staticfiles serves them automatically when DEBUG is True. In production you run collectstatic and let your web server or white-noise-style middleware serve STATIC_ROOT. Forgetting that step is why icons work locally and 404 after deploy.

Where the files go

  • myproject/
    • static/listed in STATICFILES_DIRS
      • favicon.icoadd
      • favicon-32x32.pngadd
      • apple-touch-icon.pngadd180x180
      • icon-192.pngadd
      • icon-512.pngadd
      • site.webmanifestadd
    • templates/
      • base.htmllink tags go here
    • settings.py
    • manage.py

An app-level path like blog/static/favicon.ico also works. Project-level static/ keeps site-wide icons out of any one app.

base.html

{% load static %}
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>{% block title %}My site{% endblock %}</title>

    <link rel="icon" href="{% static 'favicon.ico' %}" sizes="any">
    <link rel="icon" type="image/png" sizes="32x32" href="{% static 'favicon-32x32.png' %}">
    <link rel="apple-touch-icon" href="{% static 'apple-touch-icon.png' %}">
    <link rel="manifest" href="{% static 'site.webmanifest' %}">
  </head>
  <body>
    {% block content %}{% endblock %}
  </body>
</html>

Always use the static tag. A hardcoded /static/favicon.ico breaks when STATIC_URL changes or when ManifestStaticFilesStorage hashes the filename.

Settings that matter

SettingRoleFavicon impact
STATIC_URLURL prefix for static filesPrefixed onto every {% static %} result
STATIC_ROOTcollectstatic output directoryMust be served in production
STATICFILES_DIRSExtra project-level static dirsWhere a top-level static/ folder is registered
ManifestStaticFilesStorageContent-hashes filenamesRequires {% static %}; breaks hardcoded paths

Django favicon FAQ

Icons work in runserver but 404 in production.

collectstatic was not run, STATIC_ROOT is not being served, or WhiteNoise / your CDN is pointed at the wrong directory. Confirm the collected file exists under STATIC_ROOT and that the rendered HTML's href returns 200.

I enabled ManifestStaticFilesStorage and every icon broke.

Hardcoded /static/... paths no longer match the hashed filenames. Switch every href to {% static '...' %}, rerun collectstatic, and redeploy. The manifest mapping only works when the template tag asks for it.

Should the favicon live in an app's static/ folder?

Either works. App static folders are found automatically for installed apps; a project-level directory needs an entry in STATICFILES_DIRS. Prefer one project-level place for site-wide branding so you are not hunting through apps later.

Related platforms