IFrame Embedding Checker
Free online iframe checker: enter any webpage URL to inspect its X-Frame-Options and Content-Security-Policy frame-ancestors headers, find out whether the page can be embedded in an iframe, and confirm with a live preview. History is kept for the current browser session.
History (this session)
Saved in this tab only (sessionStorage); cleared when you close the tab. Nothing is sent to the server.
How the check works
- Enter the target URL and click Check. The server fetches the page as a real iframe request (with Sec-Fetch-Dest: iframe) and reads its response headers.
- The verdict is derived from X-Frame-Options (DENY / SAMEORIGIN block framing) and Content-Security-Policy frame-ancestors (only * or a scheme wildcard allows arbitrary third-party parents).
- The same URL is loaded in the live preview iframe so you can confirm what the browser actually does, including JavaScript frame-busting that headers cannot reveal.
What determines whether a page can be embedded?
Whether a webpage can be shown inside an <iframe> on another site is decided by the browser, based on response headers sent by the page itself. This checker performs the same inspection server-side and gives you an immediate verdict.
X-Frame-Options is the classic header: DENY forbids framing on every page, SAMEORIGIN only allows pages from the same origin to frame it, and ALLOW-FROM has been removed from modern browsers. When the header is absent, legacy rules do not block framing.
Content-Security-Policy frame-ancestors is the modern replacement. It lists the origins allowed to embed the page — for example frame-ancestors 'self' https://example.com. A value of * (or a bare scheme such as https:) permits any HTTPS parent; anything narrower blocks third-party embedding.
Headers are not the whole story: page scripts can run frame-busting code (comparing top !== self and forcing a top-level navigation), and login pages or geo-restricted endpoints may behave differently for datacenter requests. That is why every result is paired with a live preview.
Quick guide: response header setup
If you own the site, control framing directly through response headers.
Block embedding from any page
X-Frame-Options: DENY
Content-Security-Policy: frame-ancestors 'none'
Browsers refuse to render the page in any iframe — the strictest clickjacking protection.
Allow same-origin embedding only
X-Frame-Options: SAMEORIGIN
Content-Security-Policy: frame-ancestors 'self'
Only pages with the same scheme, host, and port may frame it; third-party sites are blocked.
Allow specific origins only
Content-Security-Policy: frame-ancestors 'self' https://trusted.example.com
List trusted origins in frame-ancestors; origins not listed are blocked.
Allow embedding from any page
Do not set X-Frame-Options
Content-Security-Policy: frame-ancestors *
Any site can frame the page in an iframe. Evaluate the security trade-off.
Note: X-Frame-Options is superseded by CSP frame-ancestors. When both are present, CSP wins — prefer frame-ancestors.
How does the server detect a request comes from an iframe?
Since around 2020, Chromium- and Firefox-based browsers automatically attach a set of Fetch Metadata request headers to every navigation and subresource request. The most useful one for framing checks is Sec-Fetch-Dest — it tells the server what kind of context requested the resource, without any cooperation from the requesting page.
- Sec-Fetch-Dest: document — top-level navigation, not inside any frame.
- Sec-Fetch-Dest: iframe — the request is loaded inside an <iframe> element.
- Sec-Fetch-Dest: frame — loaded inside a legacy <frame> (frameset).
- Sec-Fetch-Dest: embed / object — loaded inside an <embed> or <object> element.
This checker sends its own probe with Sec-Fetch-Dest: iframe, mirroring exactly what a real browser sends when embedding a page — so the verdict reflects how the target server actually behaves for genuine iframe requests, not just a generic fetch.
Sec-Fetch-Dest is a useful signal but not a security boundary: it is only sent by modern browsers, and non-browser clients — curl, bots, some webviews and older browsers — can omit it entirely or send an arbitrary value. A server should log or rate-limit based on it, but never rely on it alone to decide whether framing is safe; that decision still belongs to X-Frame-Options and CSP frame-ancestors, which browsers enforce independently of request headers.
On the client side, a page can also detect that it is running inside a frame without any header, e.g. by comparing window.top !== window.self (or reading window.frameElement for same-origin frames), then react — show a warning, or force a top-level redirect. That is the frame-busting technique mentioned earlier, and it works regardless of what the request headers said.
Server config examples: block iframe embedding
The snippets below show how to configure each server or framework to block iframe embedding entirely (X-Frame-Options: DENY + CSP frame-ancestors 'none') — the strictest of the recipes from the quick guide above.
server {
location / {
add_header X-Frame-Options "DENY" always;
add_header Content-Security-Policy "frame-ancestors 'none'" always;
}
}
<IfModule mod_headers.c>
Header always set X-Frame-Options "DENY"
Header always set Content-Security-Policy "frame-ancestors 'none'"
</IfModule>
app.use((req, res, next) => {
res.setHeader('X-Frame-Options', 'DENY');
res.setHeader('Content-Security-Policy', "frame-ancestors 'none'");
next();
});
// next.config.js
module.exports = {
async headers() {
return [
{
source: '/:path*',
headers: [
{ key: 'X-Frame-Options', value: 'DENY' },
{ key: 'Content-Security-Policy', value: "frame-ancestors 'none'" },
],
},
];
},
};
class SetFrameOptions
{
public function handle(Request $request, Closure $next): Response
{
$response = $next($request);
$response->headers->set('X-Frame-Options', 'DENY');
$response->headers->set('Content-Security-Policy', "frame-ancestors 'none'");
return $response;
}
}
export default {
async fetch(request) {
const response = await fetch(request);
const headers = new Headers(response.headers);
headers.set('X-Frame-Options', 'DENY');
headers.set('Content-Security-Policy', "frame-ancestors 'none'");
return new Response(response.body, { status: response.status, headers });
},
};
Only need to allow your own site, or a short allow-list, to frame the page instead of blocking everyone? Swap DENY for SAMEORIGIN, and 'none' for 'self' or an explicit list of origins — the rest of the configuration stays the same.
Known platform gotchas
General header rules aside, some well-known platforms have their own quirks — worth knowing before you assume "blocked" or "embeddable" from headers alone.
| Platform / scenario | Behavior | Why |
|---|---|---|
| YouTube watch page (youtube.com/watch) | Blocked | Use the official youtube.com/embed/{id} player URL instead — the normal watch page sends a restrictive framing policy. |
| Google Maps place page | Blocked | Only the Maps Embed API iframe URL (google.com/maps/embed) is meant to be framed. |
| Google / Microsoft OAuth login pages | Blocked | Deliberately blocked since 2015 to stop credential-phishing inside iframes; the login flow must run in a top-level window or popup. |
| Payment checkout pages (Stripe Checkout, PayPal, most bank gateways) | Blocked | Framing a payment form is a classic clickjacking vector, so processors refuse it outright. |
| GitHub repository / file pages | Blocked | Site-wide frame-ancestors 'none'; use the REST/GraphQL API or a screenshot instead of an iframe. |
| Notion / Google Docs "Publish to web" pages | Embeddable | Explicitly designed to be embedded, and the product provides ready-made embed code. |
| Wikipedia articles | Embeddable | No restrictive X-Frame-Options/CSP by default, but check the licensing and attribution terms before embedding at scale. |
Common use cases
- Decide whether a third-party widget, dashboard, or document can be embedded in your own product before writing integration code.
- Verify that your own site sends the X-Frame-Options or CSP frame-ancestors policy you intended.
- Debug clickjacking protection: understand why a page shows about:blank or a refusal message inside an iframe.
- Batch-screen candidate URLs during content aggregation or portal integration, using the session history to revisit results.
- Prepare for security reviews or penetration tests by documenting the framing policy of external dependencies.