Reader Stacks

How to Render Raw HTML Strings in Blade Templates

Blade's {{ }} escapes output by default as an XSS protection — {!! !!} skips that escaping, which means it should only ever be used on content you genuinely trust.

How to Render Raw HTML Strings in Blade Templates

Blade's default {{ $variable }} syntax automatically escapes output as an XSS protection — genuinely rendering a string as raw HTML (rather than escaped, literal text) needs the unescaped {!! !!} syntax instead, and understanding the security trade-off that comes with it matters more than the syntax itself.

The default: escaped output

{{ $post->title }}

If $post->title contained , this renders as the literal visible text of that string, not an executed script — this automatic escaping is what protects against a common category of cross-site scripting (XSS) vulnerability by default, without any extra effort.

Rendering raw, unescaped HTML

{!! $post->body !!}

This renders $post->body's actual HTML tags as real markup — genuinely necessary for content that's supposed to contain formatting, like a rich-text editor's saved output, but this is exactly the syntax that reintroduces the XSS risk {{ }} protects against by default.

The critical rule: only use {!! !!} on content you trust

Rendering raw HTML from user-submitted input without sanitizing it first is a genuine, serious security vulnerability — {!! !!} is appropriate for content from a trusted source (your own CMS content, a rich-text field that's been through a proper sanitization step) and should never be used directly on unsanitized user input.

Sanitizing user-submitted HTML before rendering it raw

composer require mews/purifier
use Mews\Purifier\Facades\Purifier;

$cleanHtml = Purifier::clean($request->input('bio'));
$user->update(['bio' => $cleanHtml]);
{!! $user->bio !!}

A dedicated HTML sanitization library like HTMLPurifier (wrapped here by the mews/purifier package) strips dangerous tags and attributes (like