HTML entity encode/decode · Guide

html_entity_decode Twig: Decoding Entities in Templates

Twig escapes output automatically, so needing to decode entities inside a template usually means the data was escaped somewhere it should not have been. Fixing that is better than adding a decode step.

What Twig gives you

There is no html_entity_decode filter built in. The closest are |raw, which stops escaping, and |striptags, which removes markup and decodes entities as a side effect:

HTML
{{ text }}              {# escaped automatically #}
{{ text|raw }}          {# not escaped — only for trusted content #}
{{ text|striptags }}    {# tags removed, entities decoded #}

In Symfony, |raw on user-supplied content is how XSS gets introduced. Reach for it only when you produced the HTML yourself and know it is safe.

Adding a filter when you truly need one

If the data genuinely arrives entity-encoded from a third party and you cannot fix the source, register a filter rather than scattering |raw:

PHP
// src/Twig/EntityExtension.php
new TwigFilter('decode_entities', fn (string $s): string =>
    html_entity_decode($s, ENT_QUOTES | ENT_HTML5, 'UTF-8')
);

{{ text|decode_entities }} then still passes through Twig autoescaping, so the decoded characters are re-escaped for HTML — which is the safe combination. Decoding and then applying |raw is not.

Fix it upstream instead

The usual root cause is double escaping: an entity-encoded value stored in the database, then escaped again by Twig, so users see & on the page.

Store raw text and let the template layer escape once. If you see literal & in rendered output, look for the code that escaped before storage — that is the bug, and decoding in the template only masks it.

Frequently asked questions

Does Twig have an html_entity_decode filter?

No. Use |striptags, or register a custom filter.

Why does my page show &?

The value was escaped before storage and escaped again by Twig. Store raw text.

Is |raw safe?

Only for HTML you generated and trust. Never for user input.

Ready to try it?

Open the free browser-based HTML entity encode/decode and apply what you just read — no sign-up, runs locally.

Open the HTML entity encode/decode tool