<h1>Configuration Handling<aclass="headerlink"href="#configuration-handling"title="Link to this heading">¶</a></h1>
<p>Applications need some kind of configuration. There are different settings
you might want to change depending on the application environment like
toggling the debug mode, setting the secret key, and other such
environment-specific things.</p>
<p>The way Flask is designed usually requires the configuration to be
available when the application starts up. You can hard code the
configuration in the code, which for many small applications is not
actually that bad, but there are better ways.</p>
<p>Independent of how you load your config, there is a config object
available which holds the loaded configuration values:
The <aclass="reference internal"href="api.html#flask.Flask.config"title="flask.Flask.config"><codeclass="xref py py-attr docutils literal notranslate"><spanclass="pre">config</span></code></a> attribute of the <aclass="reference internal"href="api.html#flask.Flask"title="flask.Flask"><codeclass="xref py py-class docutils literal notranslate"><spanclass="pre">Flask</span></code></a>
object. This is the place where Flask itself puts certain configuration
values and also where extensions can put their configuration values. But
this is also where you can have your own configuration.</p>
<sectionid="configuration-basics">
<h2>Configuration Basics<aclass="headerlink"href="#configuration-basics"title="Link to this heading">¶</a></h2>
<p>The <aclass="reference internal"href="api.html#flask.Flask.config"title="flask.Flask.config"><codeclass="xref py py-attr docutils literal notranslate"><spanclass="pre">config</span></code></a> is actually a subclass of a dictionary and
<p>Certain configuration values are also forwarded to the
<aclass="reference internal"href="api.html#flask.Flask"title="flask.Flask"><codeclass="xref py py-attr docutils literal notranslate"><spanclass="pre">Flask</span></code></a> object so you can read and write them from there:</p>
<p>To update multiple keys at once you can use the <aclass="reference external"href="https://docs.python.org/3/library/stdtypes.html#dict.update"title="(in Python v3.13)"><codeclass="xref py py-meth docutils literal notranslate"><spanclass="pre">dict.update()</span></code></a>
<h2>Debug Mode<aclass="headerlink"href="#debug-mode"title="Link to this heading">¶</a></h2>
<p>The <aclass="reference internal"href="#DEBUG"title="DEBUG"><codeclass="xref py py-data docutils literal notranslate"><spanclass="pre">DEBUG</span></code></a> config value is special because it may behave inconsistently if
changed after the app has begun setting up. In order to set debug mode reliably, use the
<codeclass="docutils literal notranslate"><spanclass="pre">--debug</span></code> option on the <codeclass="docutils literal notranslate"><spanclass="pre">flask</span></code> or <codeclass="docutils literal notranslate"><spanclass="pre">flask</span><spanclass="pre">run</span></code> command. <codeclass="docutils literal notranslate"><spanclass="pre">flask</span><spanclass="pre">run</span></code> will use the
interactive debugger and reloader by default in debug mode.</p>
<divclass="highlight-text notranslate"><divclass="highlight"><pre><span></span>$ flask --app hello run --debug
</pre></div>
</div>
<p>Using the option is recommended. While it is possible to set <aclass="reference internal"href="#DEBUG"title="DEBUG"><codeclass="xref py py-data docutils literal notranslate"><spanclass="pre">DEBUG</span></code></a> in your
config or code, this is strongly discouraged. It can’t be read early by the
<codeclass="docutils literal notranslate"><spanclass="pre">flask</span><spanclass="pre">run</span></code> command, and some systems or extensions may have already configured
<h2>Builtin Configuration Values<aclass="headerlink"href="#builtin-configuration-values"title="Link to this heading">¶</a></h2>
<p>The following configuration values are used internally by Flask:</p>
<dlclass="py data">
<dtclass="sig sig-object py"id="DEBUG">
<spanclass="sig-name descname"><spanclass="pre">DEBUG</span></span><aclass="headerlink"href="#DEBUG"title="Link to this definition">¶</a></dt>
<dd><p>Whether debug mode is enabled. When using <codeclass="docutils literal notranslate"><spanclass="pre">flask</span><spanclass="pre">run</span></code> to start the development
server, an interactive debugger will be shown for unhandled exceptions, and the
server will be reloaded when code changes. The <aclass="reference internal"href="api.html#flask.Flask.debug"title="flask.Flask.debug"><codeclass="xref py py-attr docutils literal notranslate"><spanclass="pre">debug</span></code></a> attribute
maps to this config key. This is set with the <codeclass="docutils literal notranslate"><spanclass="pre">FLASK_DEBUG</span></code> environment variable.
It may not behave as expected if set in code.</p>
<p><strong>Do not enable debug mode when deploying in production.</strong></p>
<spanclass="sig-name descname"><spanclass="pre">PROPAGATE_EXCEPTIONS</span></span><aclass="headerlink"href="#PROPAGATE_EXCEPTIONS"title="Link to this definition">¶</a></dt>
<dd><p>Exceptions are re-raised rather than being handled by the app’s error
handlers. If not set, this is implicitly true if <codeclass="docutils literal notranslate"><spanclass="pre">TESTING</span></code> or <codeclass="docutils literal notranslate"><spanclass="pre">DEBUG</span></code>
<spanclass="sig-name descname"><spanclass="pre">TRAP_HTTP_EXCEPTIONS</span></span><aclass="headerlink"href="#TRAP_HTTP_EXCEPTIONS"title="Link to this definition">¶</a></dt>
<dd><p>If there is no handler for an <codeclass="docutils literal notranslate"><spanclass="pre">HTTPException</span></code>-type exception, re-raise it
to be handled by the interactive debugger instead of returning it as a
<spanclass="sig-name descname"><spanclass="pre">TRAP_BAD_REQUEST_ERRORS</span></span><aclass="headerlink"href="#TRAP_BAD_REQUEST_ERRORS"title="Link to this definition">¶</a></dt>
<dd><p>Trying to access a key that doesn’t exist from request dicts like <codeclass="docutils literal notranslate"><spanclass="pre">args</span></code>
and <codeclass="docutils literal notranslate"><spanclass="pre">form</span></code> will return a 400 Bad Request error page. Enable this to treat
the error as an unhandled exception instead so that you get the interactive
debugger. This is a more specific version of <codeclass="docutils literal notranslate"><spanclass="pre">TRAP_HTTP_EXCEPTIONS</span></code>. If
<spanclass="sig-name descname"><spanclass="pre">SECRET_KEY</span></span><aclass="headerlink"href="#SECRET_KEY"title="Link to this definition">¶</a></dt>
<dd><p>A secret key that will be used for securely signing the session cookie
and can be used for any other security related needs by extensions or your
application. It should be a long random <codeclass="docutils literal notranslate"><spanclass="pre">bytes</span></code> or <codeclass="docutils literal notranslate"><spanclass="pre">str</span></code>. For
example, copy the output of this to your config:</p>
<spanclass="sig-name descname"><spanclass="pre">SECRET_KEY_FALLBACKS</span></span><aclass="headerlink"href="#SECRET_KEY_FALLBACKS"title="Link to this definition">¶</a></dt>
<dd><p>A list of old secret keys that can still be used for unsigning, most recent
first. This allows a project to implement key rotation without invalidating
active sessions or other recently-signed secrets.</p>
<p>Keys should be removed after an appropriate period of time, as checking each
additional key adds some overhead.</p>
<p>Flask’s built-in secure cookie session supports this. Extensions that use
<aclass="reference internal"href="#SECRET_KEY"title="SECRET_KEY"><codeclass="xref py py-data docutils literal notranslate"><spanclass="pre">SECRET_KEY</span></code></a> may not support this yet.</p>
<spanclass="sig-name descname"><spanclass="pre">SESSION_COOKIE_NAME</span></span><aclass="headerlink"href="#SESSION_COOKIE_NAME"title="Link to this definition">¶</a></dt>
<dd><p>The name of the session cookie. Can be changed in case you already have a
<spanclass="sig-name descname"><spanclass="pre">SESSION_COOKIE_DOMAIN</span></span><aclass="headerlink"href="#SESSION_COOKIE_DOMAIN"title="Link to this definition">¶</a></dt>
<dd><p>The value of the <codeclass="docutils literal notranslate"><spanclass="pre">Domain</span></code> parameter on the session cookie. If not set, browsers
will only send the cookie to the exact domain it was set from. Otherwise, they
will send it to any subdomain of the given value as well.</p>
<p>Not setting this value is more restricted and secure than setting it.</p>
<p>If this is changed after the browser created a cookie is created with
one setting, it may result in another being created. Browsers may send
send both in an undefined order. In that case, you may want to change
<aclass="reference internal"href="#SESSION_COOKIE_NAME"title="SESSION_COOKIE_NAME"><codeclass="xref py py-data docutils literal notranslate"><spanclass="pre">SESSION_COOKIE_NAME</span></code></a> as well or otherwise invalidate old sessions.</p>
<p><spanclass="versionmodified changed">Changed in version 2.3: </span>Not set by default, does not fall back to <codeclass="docutils literal notranslate"><spanclass="pre">SERVER_NAME</span></code>.</p>
<spanclass="sig-name descname"><spanclass="pre">SESSION_COOKIE_PATH</span></span><aclass="headerlink"href="#SESSION_COOKIE_PATH"title="Link to this definition">¶</a></dt>
<dd><p>The path that the session cookie will be valid for. If not set, the cookie
will be valid underneath <codeclass="docutils literal notranslate"><spanclass="pre">APPLICATION_ROOT</span></code> or <codeclass="docutils literal notranslate"><spanclass="pre">/</span></code> if that is not set.</p>
<spanclass="sig-name descname"><spanclass="pre">SESSION_COOKIE_HTTPONLY</span></span><aclass="headerlink"href="#SESSION_COOKIE_HTTPONLY"title="Link to this definition">¶</a></dt>
<dd><p>Browsers will not allow JavaScript access to cookies marked as “HTTP only”
<spanclass="sig-name descname"><spanclass="pre">SESSION_COOKIE_SECURE</span></span><aclass="headerlink"href="#SESSION_COOKIE_SECURE"title="Link to this definition">¶</a></dt>
<dd><p>Browsers will only send cookies with requests over HTTPS if the cookie is
marked “secure”. The application must be served over HTTPS for this to make
<spanclass="sig-name descname"><spanclass="pre">SESSION_COOKIE_PARTITIONED</span></span><aclass="headerlink"href="#SESSION_COOKIE_PARTITIONED"title="Link to this definition">¶</a></dt>
<dd><p>Browsers will send cookies based on the top-level document’s domain, rather
than only the domain of the document setting the cookie. This prevents third
party cookies set in iframes from “leaking” between separate sites.</p>
<p>Browsers are beginning to disallow non-partitioned third party cookies, so
you need to mark your cookies partitioned if you expect them to work in such
embedded situations.</p>
<p>Enabling this implicitly enables <aclass="reference internal"href="#SESSION_COOKIE_SECURE"title="SESSION_COOKIE_SECURE"><codeclass="xref py py-data docutils literal notranslate"><spanclass="pre">SESSION_COOKIE_SECURE</span></code></a> as well, as
<spanclass="sig-name descname"><spanclass="pre">SESSION_COOKIE_SAMESITE</span></span><aclass="headerlink"href="#SESSION_COOKIE_SAMESITE"title="Link to this definition">¶</a></dt>
<dd><p>Restrict how cookies are sent with requests from external sites. Can
be set to <codeclass="docutils literal notranslate"><spanclass="pre">'Lax'</span></code> (recommended) or <codeclass="docutils literal notranslate"><spanclass="pre">'Strict'</span></code>.
See <aclass="reference internal"href="web-security.html#security-cookie"><spanclass="std std-ref">Set-Cookie options</span></a>.</p>
<spanclass="sig-name descname"><spanclass="pre">PERMANENT_SESSION_LIFETIME</span></span><aclass="headerlink"href="#PERMANENT_SESSION_LIFETIME"title="Link to this definition">¶</a></dt>
<dd><p>If <codeclass="docutils literal notranslate"><spanclass="pre">session.permanent</span></code> is true, the cookie’s expiration will be set this
number of seconds in the future. Can either be a
<aclass="reference external"href="https://docs.python.org/3/library/datetime.html#datetime.timedelta"title="(in Python v3.13)"><codeclass="xref py py-class docutils literal notranslate"><spanclass="pre">datetime.timedelta</span></code></a> or an <codeclass="docutils literal notranslate"><spanclass="pre">int</span></code>.</p>
<p>Flask’s default cookie implementation validates that the cryptographic
<spanclass="sig-name descname"><spanclass="pre">SESSION_REFRESH_EACH_REQUEST</span></span><aclass="headerlink"href="#SESSION_REFRESH_EACH_REQUEST"title="Link to this definition">¶</a></dt>
<dd><p>Control whether the cookie is sent with every response when
<codeclass="docutils literal notranslate"><spanclass="pre">session.permanent</span></code> is true. Sending the cookie every time (the default)
can more reliably keep the session from expiring, but uses more bandwidth.
<spanclass="sig-name descname"><spanclass="pre">USE_X_SENDFILE</span></span><aclass="headerlink"href="#USE_X_SENDFILE"title="Link to this definition">¶</a></dt>
<dd><p>When serving files, set the <codeclass="docutils literal notranslate"><spanclass="pre">X-Sendfile</span></code> header instead of serving the
data with Flask. Some web servers, such as Apache, recognize this and serve
the data more efficiently. This only makes sense when using such a server.</p>
<spanclass="sig-name descname"><spanclass="pre">SEND_FILE_MAX_AGE_DEFAULT</span></span><aclass="headerlink"href="#SEND_FILE_MAX_AGE_DEFAULT"title="Link to this definition">¶</a></dt>
<dd><p>When serving files, set the cache control max age to this number of
seconds. Can be a <aclass="reference external"href="https://docs.python.org/3/library/datetime.html#datetime.timedelta"title="(in Python v3.13)"><codeclass="xref py py-class docutils literal notranslate"><spanclass="pre">datetime.timedelta</span></code></a> or an <codeclass="docutils literal notranslate"><spanclass="pre">int</span></code>.
Override this value on a per-file basis using
<aclass="reference internal"href="api.html#flask.Flask.get_send_file_max_age"title="flask.Flask.get_send_file_max_age"><codeclass="xref py py-meth docutils literal notranslate"><spanclass="pre">get_send_file_max_age()</span></code></a> on the application or
blueprint.</p>
<p>If <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">send_file</span></code> tells the browser to use conditional
requests will be used instead of a timed cache, which is usually
<spanclass="sig-name descname"><spanclass="pre">TRUSTED_HOSTS</span></span><aclass="headerlink"href="#TRUSTED_HOSTS"title="Link to this definition">¶</a></dt>
<dd><p>Validate <aclass="reference internal"href="api.html#flask.Request.host"title="flask.Request.host"><codeclass="xref py py-attr docutils literal notranslate"><spanclass="pre">Request.host</span></code></a> and other attributes that use it against
these trusted values. Raise a <aclass="reference external"href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.SecurityError"title="(in Werkzeug v3.1.x)"><codeclass="xref py py-exc docutils literal notranslate"><spanclass="pre">SecurityError</span></code></a> if
the host is invalid, which results in a 400 error. If it is <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code>, all
hosts are valid. Each value is either an exact match, or can start with
a dot <codeclass="docutils literal notranslate"><spanclass="pre">.</span></code> to match any subdomain.</p>
<p>Validation is done during routing against this value. <codeclass="docutils literal notranslate"><spanclass="pre">before_request</span></code> and
<codeclass="docutils literal notranslate"><spanclass="pre">after_request</span></code> callbacks will still be called.</p>
<p><spanclass="versionmodified added">Added in version 3.1.</span></p>
</div>
</details></dd></dl>
<dlclass="py data">
<dtclass="sig sig-object py"id="SERVER_NAME">
<spanclass="sig-name descname"><spanclass="pre">SERVER_NAME</span></span><aclass="headerlink"href="#SERVER_NAME"title="Link to this definition">¶</a></dt>
<dd><p>Inform the application what host and port it is bound to.</p>
<p>Must be set if <codeclass="docutils literal notranslate"><spanclass="pre">subdomain_matching</span></code> is enabled, to be able to extract the
subdomain from the request.</p>
<p>Must be set for <codeclass="docutils literal notranslate"><spanclass="pre">url_for</span></code> to generate external URLs outside of a
<p><spanclass="versionmodified changed">Changed in version 3.1: </span>Does not restrict requests to only this domain, for both
<codeclass="docutils literal notranslate"><spanclass="pre">subdomain_matching</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">host_matching</span></code>.</p>
</div>
<divclass="versionchanged">
<p><spanclass="versionmodified changed">Changed in version 2.3: </span>Does not affect <codeclass="docutils literal notranslate"><spanclass="pre">SESSION_COOKIE_DOMAIN</span></code>.</p>
</div>
<divclass="versionchanged">
<p><spanclass="versionmodified changed">Changed in version 1.0: </span>Does not implicitly enable <codeclass="docutils literal notranslate"><spanclass="pre">subdomain_matching</span></code>.</p>
<spanclass="sig-name descname"><spanclass="pre">APPLICATION_ROOT</span></span><aclass="headerlink"href="#APPLICATION_ROOT"title="Link to this definition">¶</a></dt>
<dd><p>Inform the application what path it is mounted under by the application /
web server. This is used for generating URLs outside the context of a
request (inside a request, the dispatcher is responsible for setting
<codeclass="docutils literal notranslate"><spanclass="pre">SCRIPT_NAME</span></code> instead; see <aclass="reference internal"href="patterns/appdispatch.html"><spanclass="doc">Application Dispatching</span></a>
for examples of dispatch configuration).</p>
<p>Will be used for the session cookie path if <codeclass="docutils literal notranslate"><spanclass="pre">SESSION_COOKIE_PATH</span></code> is not
<spanclass="sig-name descname"><spanclass="pre">PREFERRED_URL_SCHEME</span></span><aclass="headerlink"href="#PREFERRED_URL_SCHEME"title="Link to this definition">¶</a></dt>
<dd><p>Use this scheme for generating external URLs when not in a request context.</p>
<spanclass="sig-name descname"><spanclass="pre">MAX_CONTENT_LENGTH</span></span><aclass="headerlink"href="#MAX_CONTENT_LENGTH"title="Link to this definition">¶</a></dt>
<dd><p>The maximum number of bytes that will be read during this request. If
this limit is exceeded, a 413 <aclass="reference external"href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.RequestEntityTooLarge"title="(in Werkzeug v3.1.x)"><codeclass="xref py py-exc docutils literal notranslate"><spanclass="pre">RequestEntityTooLarge</span></code></a>
error is raised. If it is set to <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code>, no limit is enforced at the
Flask application level. However, if it is <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code> and the request has no
<codeclass="docutils literal notranslate"><spanclass="pre">Content-Length</span></code> header and the WSGI server does not indicate that it
terminates the stream, then no data is read to avoid an infinite stream.</p>
<p>Each request defaults to this config. It can be set on a specific
<aclass="reference internal"href="api.html#flask.Request.max_content_length"title="flask.Request.max_content_length"><codeclass="xref py py-attr docutils literal notranslate"><spanclass="pre">Request.max_content_length</span></code></a> to apply the limit to that specific
view. This should be set appropriately based on an application’s or view’s
<spanclass="sig-name descname"><spanclass="pre">MAX_FORM_MEMORY_SIZE</span></span><aclass="headerlink"href="#MAX_FORM_MEMORY_SIZE"title="Link to this definition">¶</a></dt>
<dd><p>The maximum size in bytes any non-file form field may be in a
<codeclass="docutils literal notranslate"><spanclass="pre">multipart/form-data</span></code> body. If this limit is exceeded, a 413
<aclass="reference external"href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.RequestEntityTooLarge"title="(in Werkzeug v3.1.x)"><codeclass="xref py py-exc docutils literal notranslate"><spanclass="pre">RequestEntityTooLarge</span></code></a> error is raised. If it is
set to <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code>, no limit is enforced at the Flask application level.</p>
<p>Each request defaults to this config. It can be set on a specific
<codeclass="xref py py-attr docutils literal notranslate"><spanclass="pre">Request.max_form_memory_parts</span></code> to apply the limit to that specific
view. This should be set appropriately based on an application’s or view’s
<p><spanclass="versionmodified added">Added in version 3.1.</span></p>
</div>
</details></dd></dl>
<dlclass="py data">
<dtclass="sig sig-object py"id="MAX_FORM_PARTS">
<spanclass="sig-name descname"><spanclass="pre">MAX_FORM_PARTS</span></span><aclass="headerlink"href="#MAX_FORM_PARTS"title="Link to this definition">¶</a></dt>
<dd><p>The maximum number of fields that may be present in a
<codeclass="docutils literal notranslate"><spanclass="pre">multipart/form-data</span></code> body. If this limit is exceeded, a 413
<aclass="reference external"href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.RequestEntityTooLarge"title="(in Werkzeug v3.1.x)"><codeclass="xref py py-exc docutils literal notranslate"><spanclass="pre">RequestEntityTooLarge</span></code></a> error is raised. If it
is set to <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code>, no limit is enforced at the Flask application level.</p>
<p>Each request defaults to this config. It can be set on a specific
<aclass="reference internal"href="api.html#flask.Request.max_form_parts"title="flask.Request.max_form_parts"><codeclass="xref py py-attr docutils literal notranslate"><spanclass="pre">Request.max_form_parts</span></code></a> to apply the limit to that specific view.
This should be set appropriately based on an application’s or view’s
<spanclass="sig-name descname"><spanclass="pre">TEMPLATES_AUTO_RELOAD</span></span><aclass="headerlink"href="#TEMPLATES_AUTO_RELOAD"title="Link to this definition">¶</a></dt>
<dd><p>Reload templates when they are changed. If not set, it will be enabled in
<spanclass="sig-name descname"><spanclass="pre">EXPLAIN_TEMPLATE_LOADING</span></span><aclass="headerlink"href="#EXPLAIN_TEMPLATE_LOADING"title="Link to this definition">¶</a></dt>
<dd><p>Log debugging information tracing how a template file was loaded. This can
be useful to figure out why a template was not loaded or the wrong file
<spanclass="sig-name descname"><spanclass="pre">MAX_COOKIE_SIZE</span></span><aclass="headerlink"href="#MAX_COOKIE_SIZE"title="Link to this definition">¶</a></dt>
<dd><p>Warn if cookie headers are larger than this many bytes. Defaults to
<codeclass="docutils literal notranslate"><spanclass="pre">4093</span></code>. Larger cookies may be silently ignored by browsers. Set to
<codeclass="docutils literal notranslate"><spanclass="pre">0</span></code> to disable the warning.</p>
<spanclass="sig-name descname"><spanclass="pre">PROVIDE_AUTOMATIC_OPTIONS</span></span><aclass="headerlink"href="#PROVIDE_AUTOMATIC_OPTIONS"title="Link to this definition">¶</a></dt>
<dd><p>Set to <codeclass="docutils literal notranslate"><spanclass="pre">False</span></code> to disable the automatic addition of OPTIONS
responses. This can be overridden per route by altering the
<p><spanclass="versionmodified added">Added in version 3.10: </span>Added <aclass="reference internal"href="#PROVIDE_AUTOMATIC_OPTIONS"title="PROVIDE_AUTOMATIC_OPTIONS"><codeclass="xref py py-data docutils literal notranslate"><spanclass="pre">PROVIDE_AUTOMATIC_OPTIONS</span></code></a> to control the default
<p><spanclass="versionmodified changed">Changed in version 2.3: </span><codeclass="docutils literal notranslate"><spanclass="pre">JSON_AS_ASCII</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">JSON_SORT_KEYS</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">JSONIFY_MIMETYPE</span></code>, and
<codeclass="docutils literal notranslate"><spanclass="pre">JSONIFY_PRETTYPRINT_REGULAR</span></code> were removed. The default <codeclass="docutils literal notranslate"><spanclass="pre">app.json</span></code> provider has
equivalent attributes instead.</p>
</div>
<divclass="versionchanged">
<p><spanclass="versionmodified changed">Changed in version 2.3: </span><codeclass="docutils literal notranslate"><spanclass="pre">ENV</span></code> was removed.</p>
</div>
<divclass="versionchanged">
<p><spanclass="versionmodified changed">Changed in version 2.2: </span>Removed <codeclass="docutils literal notranslate"><spanclass="pre">PRESERVE_CONTEXT_ON_EXCEPTION</span></code>.</p>
</div>
<divclass="versionchanged">
<p><spanclass="versionmodified changed">Changed in version 1.0: </span><codeclass="docutils literal notranslate"><spanclass="pre">LOGGER_NAME</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">LOGGER_HANDLER_POLICY</span></code> were removed. See
<aclass="reference internal"href="logging.html"><spanclass="doc">Logging</span></a> for information about configuration.</p>
<p>Added <codeclass="xref py py-data docutils literal notranslate"><spanclass="pre">ENV</span></code> to reflect the <spanclass="target"id="index-0"></span><codeclass="xref std std-envvar docutils literal notranslate"><spanclass="pre">FLASK_ENV</span></code> environment
variable.</p>
<p>Added <aclass="reference internal"href="#SESSION_COOKIE_SAMESITE"title="SESSION_COOKIE_SAMESITE"><codeclass="xref py py-data docutils literal notranslate"><spanclass="pre">SESSION_COOKIE_SAMESITE</span></code></a> to control the session
<p>Added <aclass="reference internal"href="#MAX_COOKIE_SIZE"title="MAX_COOKIE_SIZE"><codeclass="xref py py-data docutils literal notranslate"><spanclass="pre">MAX_COOKIE_SIZE</span></code></a> to control a warning from Werkzeug.</p>
</div>
<divclass="versionadded">
<p><spanclass="versionmodified added">Added in version 0.11: </span><codeclass="docutils literal notranslate"><spanclass="pre">SESSION_REFRESH_EACH_REQUEST</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">TEMPLATES_AUTO_RELOAD</span></code>,
<p><spanclass="versionmodified added">Added in version 0.10: </span><codeclass="docutils literal notranslate"><spanclass="pre">JSON_AS_ASCII</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">JSON_SORT_KEYS</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">JSONIFY_PRETTYPRINT_REGULAR</span></code></p>
</div>
<divclass="versionadded">
<p><spanclass="versionmodified added">Added in version 0.9: </span><codeclass="docutils literal notranslate"><spanclass="pre">PREFERRED_URL_SCHEME</span></code></p>
</div>
<divclass="versionadded">
<p><spanclass="versionmodified added">Added in version 0.8: </span><codeclass="docutils literal notranslate"><spanclass="pre">TRAP_BAD_REQUEST_ERRORS</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">TRAP_HTTP_EXCEPTIONS</span></code>,
<p><spanclass="versionmodified added">Added in version 0.7: </span><codeclass="docutils literal notranslate"><spanclass="pre">PROPAGATE_EXCEPTIONS</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">PRESERVE_CONTEXT_ON_EXCEPTION</span></code></p>
</div>
<divclass="versionadded">
<p><spanclass="versionmodified added">Added in version 0.6: </span><codeclass="docutils literal notranslate"><spanclass="pre">MAX_CONTENT_LENGTH</span></code></p>
</div>
<divclass="versionadded">
<p><spanclass="versionmodified added">Added in version 0.5: </span><codeclass="docutils literal notranslate"><spanclass="pre">SERVER_NAME</span></code></p>
</div>
<divclass="versionadded">
<p><spanclass="versionmodified added">Added in version 0.4: </span><codeclass="docutils literal notranslate"><spanclass="pre">LOGGER_NAME</span></code></p>
</div>
</details></section>
<sectionid="configuring-from-python-files">
<h2>Configuring from Python Files<aclass="headerlink"href="#configuring-from-python-files"title="Link to this heading">¶</a></h2>
<p>Configuration becomes more useful if you can store it in a separate file, ideally
located outside the actual application package. You can deploy your application, then
separately configure it for the specific deployment.</p>
<codeclass="code docutils literal notranslate"><spanclass="pre">yourapplication.default_settings</span></code> module and then overrides the values
with the contents of the file the <spanclass="target"id="index-1"></span><codeclass="xref std std-envvar docutils literal notranslate"><spanclass="pre">YOURAPPLICATION_SETTINGS</span></code>
environment variable points to. This environment variable can be set
</div><divaria-labelledby="tab-0-Q01E"class="sphinx-tabs-panel group-tab"hidden="true"id="panel-0-Q01E"name="Q01E"role="tabpanel"tabindex="0"><divclass="highlight-text notranslate"><divclass="highlight"><pre><span></span>> set YOURAPPLICATION_SETTINGS=\path\to\settings.cfg
<h2>Configuring from Data Files<aclass="headerlink"href="#configuring-from-data-files"title="Link to this heading">¶</a></h2>
<p>It is also possible to load configuration from a file in a format of
your choice using <aclass="reference internal"href="api.html#flask.Config.from_file"title="flask.Config.from_file"><codeclass="xref py py-meth docutils literal notranslate"><spanclass="pre">from_file()</span></code></a>. For example to load
<h2>Configuring from Environment Variables<aclass="headerlink"href="#configuring-from-environment-variables"title="Link to this heading">¶</a></h2>
<p>In addition to pointing to configuration files using environment
variables, you may find it useful (or necessary) to control your
configuration values directly from the environment. Flask can be
instructed to load all environment variables starting with a specific
prefix into the config using <aclass="reference internal"href="api.html#flask.Config.from_prefixed_env"title="flask.Config.from_prefixed_env"><codeclass="xref py py-meth docutils literal notranslate"><spanclass="pre">from_prefixed_env()</span></code></a>.</p>
<p>Environment variables can be set in the shell before starting the
</div><divaria-labelledby="tab-1-RmlzaA=="class="sphinx-tabs-panel group-tab"hidden="true"id="panel-1-RmlzaA=="name="RmlzaA=="role="tabpanel"tabindex="0"><divclass="highlight-text notranslate"><divclass="highlight"><pre><span></span>$ set -x FLASK_SECRET_KEY "5f352379324c22463451387a0aec5d2f"
$ set -x FLASK_MAIL_ENABLED false
$ flask run
* Running on http://127.0.0.1:5000/
</pre></div>
</div>
</div><divaria-labelledby="tab-1-Q01E"class="sphinx-tabs-panel group-tab"hidden="true"id="panel-1-Q01E"name="Q01E"role="tabpanel"tabindex="0"><divclass="highlight-text notranslate"><divclass="highlight"><pre><span></span>> set FLASK_SECRET_KEY="5f352379324c22463451387a0aec5d2f"
<spanclass="n">app</span><spanclass="o">.</span><spanclass="n">config</span><spanclass="p">[</span><spanclass="s2">"SECRET_KEY"</span><spanclass="p">]</span><spanclass="c1"># Is "5f352379324c22463451387a0aec5d2f"</span>
</pre></div>
</div>
<p>The prefix is <codeclass="docutils literal notranslate"><spanclass="pre">FLASK_</span></code> by default. This is configurable via the
<p>Values will be parsed to attempt to convert them to a more specific type
than strings. By default <aclass="reference external"href="https://docs.python.org/3/library/json.html#json.loads"title="(in Python v3.13)"><codeclass="xref py py-func docutils literal notranslate"><spanclass="pre">json.loads()</span></code></a> is used, so any valid JSON
value is possible, including lists and dicts. This is configurable via
the <codeclass="docutils literal notranslate"><spanclass="pre">loads</span></code> argument of <aclass="reference internal"href="api.html#flask.Config.from_prefixed_env"title="flask.Config.from_prefixed_env"><codeclass="xref py py-meth docutils literal notranslate"><spanclass="pre">from_prefixed_env()</span></code></a>.</p>
<p>When adding a boolean value with the default JSON parsing, only “true”
and “false”, lowercase, are valid values. Keep in mind that any
non-empty string is considered <codeclass="docutils literal notranslate"><spanclass="pre">True</span></code> by Python.</p>
<p>It is possible to set keys in nested dictionaries by separating the
keys with double underscore (<codeclass="docutils literal notranslate"><spanclass="pre">__</span></code>). Any intermediate keys that don’t
exist on the parent dict will be initialized to an empty dict.</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="n">app</span><spanclass="o">.</span><spanclass="n">config</span><spanclass="p">[</span><spanclass="s2">"MYAPI"</span><spanclass="p">][</span><spanclass="s2">"credentials"</span><spanclass="p">][</span><spanclass="s2">"username"</span><spanclass="p">]</span><spanclass="c1"># Is "user123"</span>
</pre></div>
</div>
<p>On Windows, environment variable keys are always uppercase, therefore
the above example would end up as <codeclass="docutils literal notranslate"><spanclass="pre">MYAPI__CREDENTIALS__USERNAME</span></code>.</p>
<p>For even more config loading features, including merging and
case-insensitive Windows support, try a dedicated library such as
<aclass="reference external"href="https://www.dynaconf.com/">Dynaconf</a>, which includes integration with Flask.</p>
<p>Then you just have to add a separate <codeclass="file docutils literal notranslate"><spanclass="pre">config.py</span></code> file and export
<codeclass="docutils literal notranslate"><spanclass="pre">YOURAPPLICATION_SETTINGS=/path/to/config.py</span></code> and you are done. However
there are alternative ways as well. For example you could use imports or
subclassing.</p>
<p>What is very popular in the Django world is to make the import explicit in
the config file by adding <codeclass="docutils literal notranslate"><spanclass="pre">from</span><spanclass="pre">yourapplication.default_settings</span>
<spanclass="pre">import</span><spanclass="pre">*</span></code> to the top of the file and then overriding the changes by hand.
You could also inspect an environment variable like
<codeclass="docutils literal notranslate"><spanclass="pre">YOURAPPLICATION_MODE</span></code> and set that to <codeclass="code docutils literal notranslate"><spanclass="pre">production</span></code>, <codeclass="code docutils literal notranslate"><spanclass="pre">development</span></code> etc
and import different hard-coded files based on that.</p>
<p>An interesting pattern is also to use classes and inheritance for
<p>Note that <aclass="reference internal"href="api.html#flask.Config.from_object"title="flask.Config.from_object"><codeclass="xref py py-meth docutils literal notranslate"><spanclass="pre">from_object()</span></code></a> does not instantiate the class
object. If you need to instantiate the class, such as to access a property,
then you must do so before calling <aclass="reference internal"href="api.html#flask.Config.from_object"title="flask.Config.from_object"><codeclass="xref py py-meth docutils literal notranslate"><spanclass="pre">from_object()</span></code></a>:</p>
<spanclass="k">def</span><spanclass="w"></span><spanclass="nf">DATABASE_URI</span><spanclass="p">(</span><spanclass="bp">self</span><spanclass="p">):</span><spanclass="c1"># Note: all caps</span>
<p><spanclass="versionmodified added">Added in version 0.8.</span></p>
</div>
</details><p>Flask 0.8 introduces instance folders. Flask for a long time made it
possible to refer to paths relative to the application’s folder directly
(via <codeclass="xref py py-attr docutils literal notranslate"><spanclass="pre">Flask.root_path</span></code>). This was also how many developers loaded
configurations stored next to the application. Unfortunately however this
only works well if applications are not packages in which case the root
path refers to the contents of the package.</p>
<p>With Flask 0.8 a new attribute was introduced:
<codeclass="xref py py-attr docutils literal notranslate"><spanclass="pre">Flask.instance_path</span></code>. It refers to a new concept called the
“instance folder”. The instance folder is designed to not be under
version control and be deployment specific. It’s the perfect place to
drop things that either change at runtime or configuration files.</p>
<p>You can either explicitly provide the path of the instance folder when
creating the Flask application or you can let Flask autodetect the
instance folder. For explicit configuration use the <codeclass="code docutils literal notranslate"><spanclass="pre">instance_path</span></code>
<p>The path to the instance folder can be found via the
<codeclass="xref py py-attr docutils literal notranslate"><spanclass="pre">Flask.instance_path</span></code>. Flask also provides a shortcut to open a
file from the instance folder with <codeclass="xref py py-meth docutils literal notranslate"><spanclass="pre">Flask.open_instance_resource()</span></code>.</p>