What is Clickjacking? How X-Frame-Options Stops It
Clickjacking embeds your site in a transparent iframe on an attacker's page. The user thinks they are clicking the attacker's button — but they are clicking on your page behind it. One header line prevents this.
How a clickjacking attack works
The attacker creates a page with an iframe containing your site, positioned with CSS opacity: 0 over a visible button on their page. Your bank transfer confirmation page sits invisible underneath "Click here to win a prize." The user clicks the prize button — they are actually confirming a transfer on your bank's site, logged in as themselves.
<!-- Attacker's page -->
<div style="position: relative;">
<iframe src="https://bank.example.com/transfer?amount=1000&to=attacker"
style="opacity: 0; position: absolute; top: 0; left: 0; width: 100%; height: 100%;">
</iframe>
<button style="position: relative; z-index: -1;">Click here to win!</button>
</div>
The fix — X-Frame-Options
Tell browsers not to allow your page to be embedded in iframes:
X-Frame-Options: SAMEORIGIN
With this header, browsers refuse to render your page inside an iframe on any other domain. The attack is impossible because the iframe will not load.
SAMEORIGIN vs DENY
- SAMEORIGIN — allows iframes on your own domain only. Use for admin panels or embedded tools on the same domain.
- DENY — no iframes anywhere, including your own domain. Use for login pages, payment pages, and any sensitive action.
The modern approach — CSP frame-ancestors
CSP frame-ancestors is more powerful: it supports multiple origins, regex patterns, and takes precedence over X-Frame-Options in modern browsers. Use both:
X-Frame-Options: SAMEORIGIN Content-Security-Policy: frame-ancestors 'self';
Older browsers use X-Frame-Options. Browsers supporting CSP use frame-ancestors and ignore X-Frame-Options.
Check for X-Frame-Options → HeadersFixer