Embed Code Tester

Paste the embed code a service gave you, usually a <div> plus a <script> tag or an <iframe>, and it runs in a sandboxed page below. The preview renders at desktop, tablet or phone width, and the report lists which elements stayed empty, every console message and uncaught error, and each script, image and API call with its status. The markup is checked too, for http:// URLs, relative paths, integrity attributes that cannot work and scripts that start before their element exists. Everything runs in your browser; the code is not sent to our server.

Paste embed code to see what it renders, logs and loads

Where embed code goes in your HTML

Put the element part, such as the <div> or <iframe>, inside <body> at the spot where the widget should appear. Put the script below it or just before </body>; a script with defer can also go in <head>, because it waits until the page has been parsed. With several widgets on one page, include the script once: widget scripts usually look for every matching element when they start. In a CMS, use a Custom HTML or Embed block, because the regular text editor often strips script tags.

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Our apartment</title>
    <!-- A script with defer may also go here -->
</head>
<body>
    <h1>Our apartment</h1>

    <!-- The widget renders where its element is -->
    <div data-widget="gallery" data-id="123"></div>

    <!-- Once per page, below the elements it fills -->
    <script src="https://cdn.example.com/widget.js" defer></script>
</body>
</html>

How the test works

Your code becomes the body of a page that loads in an iframe with the sandbox attribute and without allow-same-origin, so it gets a unique origin and cannot read this site's cookies, storage or page. Before your code runs, a small monitor script wraps console, fetch and XMLHttpRequest, listens for failed loads, including inside shadow roots, and reads the Resource Timing list. Each time the page changes, and once a second for the first 20 seconds, it measures every top-level element: its size, whether it has a shadow root and how many nodes it holds. An element counts as rendered once it has a width, a height and something inside it. The markup check parses your code with DOMParser, which never runs scripts or loads images.

Because of the sandbox, requests from the frame carry Origin: null, document.cookie and localStorage throw a SecurityError, and relative URLs resolve against this page. A widget that relies on any of these behaves differently here. The Test page download runs the same code on a real origin once you serve it locally.

Script embeds and iframe embeds

Script widget (element + script)Iframe
Runs inYour page, with your DOM, cookies and CSSA separate page inside a frame
Blocked byYour Content-Security-Policy (script-src, connect-src, img-src)The framed page's X-Frame-Options or frame-ancestors, and your frame-src
StylingInherits your CSS unless it renders into a shadow rootIsolated from your CSS
HeightGrows with its contentFixed unless the page reports its height to a resize script
Fails whenThe script or its API calls are blocked, or it starts before its element existsThe page refuses to be framed or is served over http://

Why it works here but not on your site

The preview sends no Content-Security-Policy. If your site sends one, it has to list the script's host in script-src, its API in connect-src and its images in img-src. Your CSS also reaches a widget that does not use a shadow root, so your fonts, resets and box-sizing rules change how it looks. Some vendors tie a key to a domain and reject requests from any other origin. In a single-page app, React, Vue or another framework may mount the element after the script has run, or re-render it later, and the widget then finds nothing or loses its content; call the widget's own init or scan function after the element is mounted.

How to use the Embed Code Tester (Preview Script and Iframe Widgets) tool

  1. Paste the embed code into the box: a widget's element and script tags, an iframe, or a whole HTML page.
  2. Click Run Code. The code runs in a sandboxed frame below, with a small monitor script loaded first.
  3. Read the verdict and the Rendered elements list, which shows each top-level element with its size, shadow root and data attributes. Elements a script appended to the page are marked Added by script.
  4. Look through Console and Network for uncaught errors, blocked scripts and failed API calls, and through Snippet check for problems in the markup itself, such as http:// URLs, relative paths or an integrity hash that cannot work.
  5. Switch the preview between full, desktop, tablet and phone width, then copy or download the Test page to run the code outside the sandbox. Dummy Data loads a working gallery widget.

How to test embed code in code

curl

# The script: expect 200 and a JavaScript content type, not text/html from an error page
curl -sS -o /dev/null -w "%{http_code} %{content_type}\n" https://cdn.example.com/widget.js

# The widget's API, asked the way a browser on your site asks it
curl -sS -o /dev/null -D - -H "Origin: https://yoursite.example" https://api.example.com/widget/123 \
  | grep -i "^access-control-allow-origin"

The second command must print * or exactly your origin. If it prints nothing, browsers block the call even though curl gets the data.

JavaScript (Playwright)

// npm i -D playwright && npx playwright install chromium
import { chromium } from "playwright";

const snippet = `<div id="widget"></div>
<script src="https://cdn.example.com/widget.js" defer></script>`;

const browser = await chromium.launch();
const page = await browser.newPage();
const problems = [];
page.on("console", (m) => m.type() === "error" && problems.push(m.text()));
page.on("pageerror", (e) => problems.push("Uncaught " + e.message));
page.on("requestfailed", (r) => problems.push(`${r.failure()?.errorText} ${r.url()}`));
page.on("response", (r) => r.status() >= 400 && problems.push(`${r.status()} ${r.url()}`));

// Serve the snippet on a made-up https origin, so CORS and cookies behave as on a live site
await page.route("https://test.example/", (route) =>
    route.fulfill({ contentType: "text/html", body: `<!doctype html><body>${snippet}</body>` }));
await page.goto("https://test.example/");

const rendered = await page
    .waitForFunction(() => document.querySelector("#widget")?.getBoundingClientRect().height > 0, null, { timeout: 10000 })
    .then(() => true, () => false);
console.log(rendered ? "rendered" : "empty after 10 s", problems);
await browser.close();

Run it in CI against every page that carries the widget, so a vendor change that breaks rendering fails the build.

Common errors and how to fix them

Uncaught TypeError: Cannot read properties of null (reading 'appendChild')
The script ran before its element existed: it sits above the element and has no defer. Add defer to the script tag, or move it below the element.
Access to fetch at '...' from origin '...' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
The widget's API does not accept the page's origin. Vendors that tie a key to a domain answer other sites this way, so add your domain in the vendor's dashboard. In this tool the origin is null, which means an API with a domain list fails here even when your site is on it.
Refused to load the script '...' because it violates the following Content Security Policy directive: "script-src 'self'"
Your page's CSP does not list the widget's host. Add it to script-src, and add the API host to connect-src and the image host to img-src, or the script loads and then fails on its first request.
Failed to find a valid digest in the 'integrity' attribute for resource '...'. The resource has been blocked.
The file no longer matches the hash, because the URL is a version range or the vendor replaced the file. Pin an exact version and generate a new hash, or drop integrity for URLs that change on purpose.
Mixed Content: The page at 'https://...' was loaded over HTTPS, but requested an insecure script 'http://...'. This request has been blocked; the content must be served over HTTPS.
Change the src to https://. If the vendor has no https version, the widget cannot run on a secure page.

Good to know

The sandbox attribute gives the preview frame a unique origin, so the code cannot reach webdevutility.com's cookies, storage or page. In return, requests carry Origin: null, document.cookie and localStorage throw a SecurityError, and relative URLs resolve against this page. Opening the downloaded test page as a file:// URL has the same null origin; serve its folder with npx serve or python3 -m http.server to get a real one.

Errors thrown inside a script from another origin reach the page as "Script error." with no message or line, because browsers hide them unless the script tag has crossorigin="anonymous" and the server sends CORS headers. Inside the sandbox every external script counts as another origin. DevTools always shows the full error.

Specifications and references

This tool follows the specifications below. Read them when you need the exact normative wording, for example to settle an edge case between two implementations.

Frequently Asked Questions

Where do I put embed code in my HTML?

Put the element, such as the <div> or <iframe>, inside <body> where the widget should appear, and the <script> tag below it or just before </body>. A script with defer can also go in <head>. Include the script once, even for several widgets on a page. In WordPress, use a Custom HTML block; most site builders have a similar Embed or Code block.

Why does my embed code show nothing?

Usually the script never ran, or it ran and found nothing to fill. Your page's Content-Security-Policy, an ad blocker or mixed content can block it. A script placed above its element without defer runs before that element exists. Or the element's id or data attributes do not match what the script looks for. The tool shows these as a failed request in Network, an error in Console or an element marked Empty.

What is the difference between a script embed and an iframe embed?

A script embed runs in your page: it reads your DOM, inherits your CSS unless it uses a shadow root, and calls its API with CORS, so your Content-Security-Policy must allow it. An iframe embed loads a separate page in a frame, isolated from your CSS and scripts, and the framed page's X-Frame-Options or frame-ancestors header decides whether it may appear on your site at all.

Is it safe to run embed code here?

The code runs in an iframe with the sandbox attribute and no allow-same-origin, so it gets a unique origin. It cannot read this site's cookies, storage or page, and it cannot navigate this tab. Its scripts and images load straight from their own servers into your browser, and the code is not sent to our API.

Why does the widget work here but not on my website?

The preview has no Content-Security-Policy and almost no CSS. If your site sends a CSP, add the script's host to script-src, its API to connect-src and its image host to img-src. Also check that your CSS does not restyle the widget, that the vendor allows your domain, and that a framework such as React does not mount the element after the script has run.

Why does it work on my website but not here?

The sandbox gives the code a unique origin. Requests carry Origin: null, so an API that only accepts listed domains refuses them, and document.cookie and localStorage throw a SecurityError. Relative URLs also resolve against webdevutility.com. Download the Test page and serve it from a local server to run the same code on a real origin.

Related

Check whether the page in an iframe src allows framing with the iframe checker, tidy a one-line snippet with the HTML formatter, or escape it for a tutorial with the HTML encoder.

More URL Tools

Browse all url tools

Copied to clipboard!