X-Frame-Options
X-Frame-Options header explainer online free. Understand DENY, SAMEORIGIN for clickjacking protection. X-Frame-Options guide.
What is X-Frame-Options?
X-Frame-Options is an HTTP response header used to indicate whether a browser should be
allowed to render a page in a <frame>, <iframe>, <embed> or <object>. It helps prevent clickjacking attacks by controlling who can embed your pages.
DENY
The page cannot be displayed in a frame, regardless of the site attempting to do so.
- Banking / financial sites
- Admin panels
- Login pages
SAMEORIGIN
The page can only be displayed in a frame on the same origin as the page itself.
ALLOW-FROM
DeprecatedThe page can only be displayed in a frame on the specified origin. (Deprecated in most browsers)
Generated Headers
X-Frame-Options: DENY
Content-Security-Policy: frame-ancestors 'none'
CSP frame-ancestors vs X-Frame-Options
frame-ancestors in Content-Security-Policy is the modern replacement for X-Frame-Options.
It offers more flexibility (multiple origins, wildcards) and is recommended for new implementations.
For maximum compatibility, use both headers.
Features
- Visual builder for X-Frame-Options and CSP frame-ancestors headers
- Options: DENY, SAMEORIGIN, ALLOW-FROM (legacy), and CSP-based frame-ancestors
- Allowlist specific domains for embedding via iframe
- Implementation snippets for Nginx, Apache, Express, and meta tag
- Live preview of how the header affects iframe embedding
- Explanation of clickjacking attacks and how the header prevents them
Common Use Cases
- Protect a web application from clickjacking attacks
- Allow your app to be embedded in iframes from specific trusted domains
- Completely block iframe embedding of a login or payment page
- Migrate from the legacy X-Frame-Options header to modern CSP frame-ancestors
- Audit which pages on your site can be embedded in iframes
Clickjacking & Frame Protection
Clickjacking is an attack where a malicious page embeds your web app in a hidden or transparent iframe, tricking users into clicking on your buttons (submitting forms, making payments, changing settings) while thinking they are clicking on the attacker's content.
Protection uses the X-Frame-Options HTTP header (legacy) or CSP frame-ancestors directive (modern). Both tell browsers under what conditions your page may be framed:
DENY— never allow framingSAMEORIGIN— only allow framing from the same originframe-ancestors 'none'— CSP equivalent of DENY (preferred)frame-ancestors 'self' https://partner.com— allow specific origins
CSP frame-ancestors is the modern standard — it supports multiple origins and overrides X-Frame-Options. Use it instead of X-Frame-Options when possible.
Examples
X-Frame-Options: DENYX-Frame-Options: SAMEORIGINContent-Security-Policy: frame-ancestors 'self' https://trusted-partner.comFrequently Asked Questions
Prefer CSP frame-ancestors — it supports multiple origins, uses a modern standard, and CSP overrides X-Frame-Options when both are present. For maximum compatibility with older browsers, you can set both. If only setting one, use CSP frame-ancestors.
Yes: embedded widgets, payment frames, analytics dashboards, and partner integrations legitimately embed content in iframes. In this case, use frame-ancestors 'self' https://trusted-partner.com to allow only the specific trusted domain, not a wildcard.
Yes. If your app uses iframes internally (e.g., to embed a map, payment widget, or same-origin rich text editor), use SAMEORIGIN instead of DENY. For fine-grained control over which pages can be framed vs. which can frame others, apply the header selectively at the route level.
Native mobile apps do not use iframes, so traditional clickjacking is not a concern. However, mobile webviews can render web content and some webview implementations may be susceptible to UI redressing attacks. When building hybrid apps, apply the same frame protection headers to the web content served to the webview.
💡 Tips
- Add <code>X-Frame-Options: SAMEORIGIN</code> and <code>Content-Security-Policy: frame-ancestors 'self'</code> to your baseline response headers today — it takes 5 minutes and provides immediate clickjacking protection.
- Apply DENY to sensitive pages (login, payment, account settings) even if you allow SAMEORIGIN elsewhere.
- Test your header is working by trying to embed your page in a simple iframe: <code><iframe src="https://yoursite.com"></iframe></code> — the browser should block it.
- Use browser DevTools → Network → Response Headers to confirm the header is being delivered on each request.