# Jinja Escaping

Sometimes we may need to include some text in our HTML templates that Jinja2 will want to parse. For example, if we're writing a tutorial about Jinja2!

<p>This is how you write a Jinja2 for loop:</p>

<pre><code>
{% for user in users %}
	<p>{{ user['name'] }}</p>
{% endfor %}
</code></pre>

If we do this, Jinja2 will try to run through the loop and evaluate it. If we don't pass in a users variable, we'll get an error.

This is where the Jinja2 raw block comes in handy:

<p>This is how you write a Jinja2 for loop:</p>

<pre><code>
{% raw %}
{% for user in users %}
	<p>{{ user['name'] }}</p>
{% endfor %}
{% endraw %}
</code></pre>

For more information, please check the official documentation (opens new window).

# raw vs safe and e

The raw block tells Jinja2 to not render the Jinja2 code before sending it to the user.

The e block escapes HTML code so that the browser doesn't use it to paint in the browser window (it doesn't run it as HTML).

The safe block unescapes HTML code that has been previously escaped, so that the browser does use it and run it as HTML.

Do you need to use both safe and e?

No. Just use one of the two, depending on your application settings.

As of Jinja 3, autoescaping is disabled when used on its own, but autoescaping is enabled in Flask apps[1] in certain templates. You don't need to escape variables in .html, .htm, .xml, or .xhtml templates.

You do need to escape variables if you use .jinja2, .j2, or .jinja templates.

  • app.py
from flask import Flask, render_template

app = Flask(__name__)

html_code = """<div><p>This is a <strong>Test</strong>.</p></div>"""


@app.route("/")
def home():
    return render_template("main.jinja2", html_code=html_code)
  • main.jinja2
<!DOCTYPE html>
<html>
<head></head>
<body>
<div>
{{ html_code }}

{{ html_code | safe }}

{{ html_code | e }}

{% raw %}
{{ html_code }}
{% endraw %}
</div>
</body>
</html>
  • Here's the browser output:
<html><head></head>
<body>
<div>
<div><p>This is a <strong>Test</strong>.</p></div>

<div><p>This is a <strong>Test</strong>.</p></div>

&lt;div&gt;&lt;p&gt;This is a &lt;strong&gt;Test&lt;/strong&gt;.&lt;/p&gt;&lt;/div&gt;


{{ html_code }}
</div>

</body></html>

In my code, autoescaping is disabled (as is by default). Therefore, the | safe filter doesn't do anything. It unescapes something that has been escaped, but nothing's been escaped.

The | e filter does do something: it escapes the HTML. Then the browser treats it as text that it doesn't have to run--it just displays it.

I've included the raw block in there to show you that that simply displays . Jinja2 never ran that, so it is shown as plain text.

If you disable autoescaping (which the documentation suggests would result in a performance boost (opens new window)), then you should escape all potentially unsafe strings, such as those that could contain untrusted HTML code. For example, any text that is coming from your users.

Enjoyed this article?
You'll love the complete video course!

  • Complete video lessons for each topic
  • Get the most out of your learning
  • Build a portfolio of projects
  • Get one-on-one help from a real person

Get the video course


  1. Jinja setup (Flask docs) (opens new window) ↩ī¸Ž