Web security requires controlling how content is displayed and interacted with across websites. One common risk is clickjacking, where attackers embed a legitimate page within a hidden frame to trick users. The X-Frame-Options header is a key tool to defend against such threats.
Overview
What are X-Frame-Options?
X-Frame-Options is an HTTP response header that controls whether a web page can be embedded within a frame, iframe, or object on another website. It is primarily used to prevent clickjacking attacks, where malicious sites attempt to trick users into interacting with hidden or disguised elements on a legitimate page.
Why are X-Frame-Options Used?
- Prevent clickjacking: Stops attackers from embedding pages in hidden frames to trick users into performing unintended actions.
- Enhance security for sensitive pages: Protects login forms, payment pages, and dashboards from being framed by untrusted sites.
- Maintain control over content embedding: Ensures that content appears only in approved contexts, reducing the risk of UI manipulation.
How X-Frame-Options Works
- Browser enforcement: Browsers check the X-Frame-Options header in the HTTP response and block or allow framing based on its value.
- Request evaluation: When a page is requested within a frame, the browser compares the origin of the parent page against the header directive.
- Action on violation: If framing is not permitted, the browser prevents the page from being rendered in the frame entirely.
X-Frame-Options Header Values and What They Do
- Deny: Blocks all domains from framing the page. This provides maximum protection when framing is not required.
- SameOrigin: Allows only pages from the same origin (domain) to embed the content. Ideal for internal pages that may need self-framing.
- Allow-From [URI]: Permits a specific external domain to frame the page. Useful when controlled cross-origin embedding is necessary.
This article explains the purpose of X-Frame-Options, how it works, its configuration options, and best practices for implementation and testing.
What Is the X-Frame-Options Header?
X-Frame-Options is an HTTP header that tells browsers whether a web page can be displayed inside a frame, iframe, or object on another website. It instructs the browser to either block or allow the page from being embedded based on the specified directive.
Its main purpose is to protect users from clickjacking, a type of attack where malicious sites trick users into clicking hidden buttons or links. This header is essential for pages that handle sensitive information such as login forms, dashboards, and payment screens.
What Threats Do X-Frame-Options Prevent?
Web pages can be embedded in other sites without the owner’s knowledge, creating opportunities for sophisticated attacks. The X-Frame-Options header prevents these risks by instructing browsers on which domains are allowed to frame your content.
Here are the main threats that X-Frame-Options helps protect against:
- Clickjacking of actions: Attackers can hide buttons or links behind fake content. For example, a user might unknowingly approve a financial transaction or change account settings. X-Frame-Options blocks such framing attempts entirely.
- Interface overlay manipulation: Malicious sites can layer their own elements over your page to make it appear interactive while capturing user clicks. Setting the header restricts framing to trusted sources only.
- Data interception on forms: Login screens, payment forms, and other input fields are at risk when embedded on external domains. Unauthorized framing can capture sensitive credentials or payment information.
- Brand and reputation misuse: Framing your pages on untrusted sites can be used to display misleading content or ads, damaging user trust. Controlling framing ensures your content is seen only in the intended context.
How X-Frame-Options Mitigates Clickjacking Attacks
Clickjacking works by embedding a page inside a hidden frame on a malicious site, tricking users into performing actions they cannot see. The X-Frame-Options header blocks these framing attempts, ensuring that sensitive interactions on your site remain secure.
Here are the ways X-Frame-Options provides protection:
- Deny all framing: Completely blocks any site from embedding the page. This prevents attackers from layering deceptive frames over sensitive pages like login screens, payment forms, or administrative dashboards.
- Allow same-origin framing: Restricts embedding to pages from the same domain. Internal tools or widgets that require framing remain functional while external attacks are blocked.
- Allow specific domain: Grants permission to a trusted partner site to embed your page. This allows controlled sharing of content, such as analytics dashboards or widgets, without exposing users to unknown third-party risks.
- Immediate browser enforcement: Browsers check each framing attempt in real time. Unauthorized frames are blocked before the page renders, preventing hidden overlays or intercepted clicks from reaching users.
- Reduced attack surface for UI elements: By controlling framing at the browser level, buttons, forms, and interactive widgets cannot be manipulated by malicious overlays, reducing the chance of unintended actions or data leaks.
How to Implement X-Frame-Options
Implementing X-Frame-Options requires a clear process to ensure pages are protected without breaking legitimate use cases. Follow these steps to set it up correctly:
Step 1: Identify pages that need protection
Start by listing all pages that handle sensitive operations, such as login forms, dashboards, payment pages, or administrative panels. These pages should always have X-Frame-Options applied to prevent clickjacking or unauthorized embedding.
Step 2: Choose the right directive
Decide how strictly each page should be framed:
- Use DENY to block all external framing for maximum security.
- Use SAMEORIGIN to allow internal pages from the same domain to embed content.
- Use ALLOW-FROM [URI] to permit trusted third-party domains when necessary.
Step 3: Configure the web server or application
Add the header to your server or application so that browsers enforce it automatically.
- Apache:
Header always set X-Frame-Options “SAMEORIGIN”
- Nginx:
add_header X-Frame-Options “DENY”;
- Application code (Express.js example):
app.use((req, res, next) => { res.setHeader(“X-Frame-Options”, “DENY”);
next();
});
Step 4: Test the implementation
After setting the header, verify it is applied to all relevant pages. Use browser developer tools or security testing tools to confirm that framing attempts from unauthorized domains are blocked.
Step 5: Maintain and monitor
Ensure new pages inherit the X-Frame-Options header. Periodically review server and application settings, especially when introducing trusted third-party domains or internal tools that may require framing.
Common Misconfigurations and How to Avoid Them
Even when X-Frame-Options is implemented, improper configuration can leave pages exposed. Recognizing these common mistakes helps ensure that sensitive pages remain protected.
- Wrong directive for sensitive pages: Using SAMEORIGIN or ALLOW-FROM on pages like login forms or payment screens can allow unintended framing. Use DENY for maximum security.
- Header missing on certain pages: Dynamic routes, dashboards, or embedded forms sometimes don’t inherit the header. Audit all pages to ensure consistent coverage.
- Server misconfiguration: Incorrect Apache or Nginx rules, such as placing the header in the wrong context or syntax errors, prevent browsers from enforcing restrictions.
- Relying solely on X-Frame-Options: Some older browsers or nonstandard environments may ignore the header. Pair it with a CSP frame-ancestors directive for broader protection.
- Skipping testing after changes: Adding new pages, updating frameworks, or integrating third-party code can remove or override headers. Regular testing ensures continued enforcement.
Transitioning from X-Frame-Options to Content Security Policy
X-Frame-Options provides basic protection against framing attacks, but it has limitations. Modern web security practices recommend moving to a Content Security Policy (CSP) using the frame-ancestors directive, which offers more flexibility and broader browser support.
Step 1: Understand the limitations of X-Frame-Options
X-Frame-Options does not support multiple allowed domains, and some directives like ALLOW-FROM are poorly supported across browsers. CSP overcomes these restrictions and provides granular control over which sites can embed your content.
Step 2: Map your existing directives to CSP
Identify all pages currently using X-Frame-Options and note their directives (DENY, SAMEORIGIN, ALLOW-FROM). Translate these rules into equivalent CSP frame-ancestors policies. For example:
- DENY > Content-Security-Policy: frame-ancestors ‘none’;
- SAMEORIGIN > Content-Security-Policy: frame-ancestors ‘self’;
- ALLOW-FROM example.com > Content-Security-Policy: frame-ancestors https://example.com;
Step 3: Implement CSP headers on the server or application
Set CSP headers via web server configuration or application code, ensuring they are applied consistently across all relevant pages.
Step 4: Test thoroughly across browsers
Unlike X-Frame-Options, CSP is supported differently depending on the browser. Test each page in multiple browsers to confirm framing restrictions are enforced correctly.
Step 5: Phase out X-Frame-Options
Once CSP is confirmed to cover all necessary use cases, remove X-Frame-Options to simplify configuration and avoid conflicts. Maintain CSP policies going forward for consistent protection.
Why Use Requestly to Test X-Frame-Options Headers
Testing how your website responds to different X-Frame-Options configurations is crucial for ensuring robust security against clickjacking attacks. Requestly is a powerful Chrome extension that allows you to modify HTTP headers on the fly, making it an ideal tool for this purpose.
With Requestly, you can simulate various scenarios by modifying the X-Frame-Options header in real-time, without making permanent changes to your server configuration. This flexibility enables comprehensive testing of your site’s behavior under different security settings.
Here are some ways Requestly can assist in testing X-Frame-Options headers:
- Simulate Same-Origin Embedding: Set the X-Frame-Options header to SAMEORIGIN and verify that your page can be embedded within an iframe on the same domain.
- Test Cross-Origin Blocking: Set the header to DENY and attempt to embed your page from a different origin to ensure it is blocked as expected.
- Override Headers for Specific Pages: Use Requestly’s targeting rules to apply different X-Frame-Options settings to specific URLs, allowing for granular testing across your site.
- Monitor Header Modifications: Observe how changes to the X-Frame-Options header affect your site’s embedding behavior in real-time, aiding in troubleshooting and optimization.
Conclusion
X-Frame-Options is a critical security header that prevents clickjacking by controlling which sites can embed your web pages. Proper use of directives like DENY, SAMEORIGIN, and ALLOW-FROM protects sensitive pages, maintains the integrity of interactive elements, and ensures that content is displayed only in trusted contexts.
Requestly simplifies testing and validation of X-Frame-Options headers by allowing real-time modifications and simulations without changing server configurations. It helps developers verify different framing scenarios, troubleshoot issues, and ensure that security settings are applied consistently across all pages.

