Embedding content safely: iframe, sandbox and allow

Embed maps, videos and other sites, and limit what that third-party code can do on your page.

  • Beginner
  • 6 min read
  • Updated 17 Oct 2026

What you will learn

  • Embed third-party content
  • Restrict embeds with sandbox
  • Grant only the browser features an embed needs with allow

Before you start

An iframe places another web page inside yours: a map, a video player, a booking widget, a payment form. Each embed runs someone else's code on your page, so it is worth knowing how to limit what it can do, and how to stop it slowing your page down.

A basic embed

HTML
<iframe
  src="https://www.example.com/booking-widget"
  title="Class booking calendar"
  width="600"
  height="400"
  loading="lazy">
</iframe>
AttributePurpose
srcThe URL of the embedded page
titleAn accessible name. Screen readers announce it when they reach the frame.
width and heightThe size of the frame in CSS pixels, which also reserves space
loading="lazy"Defers loading until the frame is near the viewport

Always add a title that says what the frame contains. Without it, screen reader users hear only "frame" and have to go inside to find out what it is.

iframe content cannot be styled from your page's CSS. You control only the frame itself: its size, border and position. To make an embed scale with its container, keep the proportions with CSS:

HTML
<style>
  .video-embed {
    width: 100%;
    height: auto;
    aspect-ratio: 16 / 9;
    border: 0;
  }
</style>
<iframe class="video-embed"
  src="https://www.youtube-nocookie.com/embed/VIDEO_ID"
  title="Video: shaping a sourdough loaf"
  allow="encrypted-media; picture-in-picture; fullscreen"
  referrerpolicy="strict-origin-when-cross-origin"
  loading="lazy">
</iframe>

Replace VIDEO_ID with a real video ID. The youtube-nocookie.com domain is YouTube's privacy-enhanced embed mode.

Same-origin and cross-origin

Browsers keep pages from different origins apart. An origin is the scheme, domain and port, such as https://example.com. A cross-origin iframe cannot read your page, and your page cannot read it. That protection is automatic.

What the embedded page can do by default is quite a lot: run JavaScript, submit forms, open pop-up windows, play media and, in some cases, navigate your whole page away. sandbox and allow let you take those powers away.

sandbox: switch everything off, then allow what is needed

Adding sandbox with no value applies every restriction. The framed page:

  • cannot run scripts,
  • cannot submit forms,
  • cannot open pop-ups or new windows,
  • cannot navigate the top-level page,
  • is treated as coming from a unique, opaque origin, so it cannot use its own cookies or storage.

You then add back only the capabilities the embed needs, as space-separated tokens:

TokenAllows
allow-scriptsRunning JavaScript
allow-formsSubmitting forms
allow-popupsOpening new windows, for example from target="_blank" links
allow-popups-to-escape-sandboxLetting those new windows run without the sandbox
allow-same-originKeeping the frame's real origin, so it can use its own cookies and storage
allow-top-navigation-by-user-activationNavigating your page, but only after the user clicks inside the frame
allow-downloadsStarting downloads
allow-modalsUsing alert(), confirm() and print()

A widget that needs scripts and forms but should never redirect your page or open pop-ups:

HTML
<iframe
  src="https://widgets.example.com/newsletter-signup"
  title="Newsletter sign-up form"
  width="400"
  height="300"
  sandbox="allow-scripts allow-forms">
</iframe>

Test sandboxed embeds carefully. If something does not work, the Console usually reports which action the sandbox blocked.

Never combine allow-scripts and allow-same-origin for a page from your own origin. The framed page could then use script to remove its own sandbox attribute, and the sandbox would give no protection at all. For third-party content on a different origin, the combination is common and still limits other actions such as pop-ups and top-level navigation.

Showing untrusted HTML

sandbox is also useful for showing HTML you do not control, such as user-submitted content or an HTML email preview. The srcdoc attribute holds the HTML directly:

HTML
<iframe
  title="Email preview"
  sandbox
  srcdoc="<p>Hello <b>Sam</b>, your order is ready.</p>">
</iframe>

With a bare sandbox, no scripts in that HTML run.

allow: grant browser features

Powerful browser features such as the camera, microphone, geolocation, full screen and payment are controlled by a Permissions Policy. Cross-origin frames cannot use most of them unless your page grants them with allow:

HTML
<iframe
  src="https://video.example.com/player/123"
  title="Video: our bakery tour"
  allow="fullscreen; picture-in-picture; autoplay"
  width="640"
  height="360">
</iframe>

Grant only what the embed needs. A video player needs fullscreen and perhaps picture-in-picture; it does not need camera or geolocation. Video providers often supply embed code with a long allow list; trim it to what you use.

referrerpolicy

When the iframe loads, the browser normally tells the embedded site which page it is on, through the Referer header. referrerpolicy controls how much is shared:

ValueSent to a cross-origin embed
no-referrerNothing
originOnly your origin, such as https://example.com/
strict-origin-when-cross-originYour origin over HTTPS, the full URL for same-origin requests. This is the browser default.
same-originNothing for cross-origin requests

If your URLs contain anything private, such as search terms or account identifiers, use no-referrer or origin. Some embeds, including video players that check which sites embed them, need at least the origin to work.

Stopping your site being framed

The reverse problem is other sites embedding your pages, for example to trick people into clicking hidden buttons (clickjacking). That is controlled on the server with the Content-Security-Policy: frame-ancestors header, or the older X-Frame-Options header, not with HTML. Pages such as sign-in and account settings should refuse framing.

Performance

Every iframe loads a whole page with its own scripts, styles and requests. A few habits keep embeds from slowing your page:

  • Add loading="lazy" to embeds below the first screen.
  • Set width and height, or aspect-ratio in CSS, to avoid layout shift.
  • For heavy video embeds, consider showing a thumbnail image with a play button that loads the real iframe only when clicked. This is often called a facade.

Ask whether you need an iframe at all. A static map image linked to the full map, or a link to a video, is lighter and often just as useful.

Summary

  • Give every iframe a descriptive title, dimensions and, below the first screen, loading="lazy".
  • Use sandbox to remove capabilities, then add back only the tokens the embed needs.
  • Never combine allow-scripts and allow-same-origin for content from your own origin.
  • Use allow to grant only the browser features an embed requires.
  • Set referrerpolicy to protect private URLs, and block framing of your own sensitive pages with server headers.

Further reading