JavaScript Playground — Run JS in Your Browser

A focused JavaScript scratchpad: write a snippet, press Run, and read the console output beside it. The code executes in a sandboxed Worker inside an iframe and never leaves the tab.

Ready — press Run to start the sandbox. Nothing is uploaded.

Consolestdout and errors
 

The sandbox is a separate opaque-origin iframe. Stop discards it, which is the reliable way to end a tight loop. Completion includes browser APIs; DOM-only APIs such as document are not available in the Worker — use the HTML playground for DOM work.

What this playground does

This is a small JavaScript runner with one job: take a snippet, execute it in the browser, and show what it logged. It is useful for checking a language detail, reducing a failing function to a few lines, trying a regular expression, or confirming what an asynchronous call returns before you paste it into a project. The editor is a full code editor with JavaScript syntax highlighting, line numbers, bracket matching, completion for common browser APIs and Ctrl/Cmd + Enter to run. For the execution model behind the sandbox, see running code in the browser without a server.

This is not a Node.js environment and not a complete web page. There is no file system, no package manager and no visible DOM preview. When the point is a rendered result, use the HTML, CSS and JavaScript playground; when the point is the value of a function or the shape of an object, this page keeps the feedback tighter.

How a run works

On the first Run the page creates a sandboxed iframe and loads a tiny runner into it. The runner starts a Web Worker from a Blob, and the snippet is sent by postMessage through the iframe to that Worker, never inserted into the parent document. The Worker evaluates the source as the body of an async function, which is why top-level await works and why a returned promise is awaited before the run is marked finished. Classic import declarations are not available because the snippet is not parsed as a module; dynamic import() works when the URL is reachable and CORS allows it.

Before evaluating, the runner replaces console.log, console.info, console.warn and console.error with wrappers that both forward to the output panel and call the original browser console. It also listens for Worker errors and unhandled promise rejections. Strings are printed unchanged; objects are JSON-serialised with a circular-reference marker; errors use their stack when one is available. The original messages remain in DevTools, where you can expand objects and inspect stack frames properly.

The sandbox boundary

The iframe carries sandbox="allow-scripts" and deliberately omits allow-same-origin. Its origin is opaque, and the Worker created inside it inherits that boundary: code cannot read this site’s DOM, cookies or localStorage, and cannot navigate the parent tab. A Worker has no DOM at all, so there is no document to manipulate and no preview to display. That distinction matters if you expected a live HTML preview — use the HTML playground for that.

A sandbox is an isolation boundary, not a content filter. The snippet can still call fetch, load remote resources, open sockets through browser APIs that allow them, and consume CPU or memory until you press Stop or close the tab. Cross-origin requests remain subject to CORS, and storage APIs usually fail in an opaque origin. Do not paste production secrets into a page you do not control; the tool does not upload the source, but code you write can still make a request that contains a secret.

Reading the result

Output arrives in the order the snippet wrote it. A successful run ends with “Finished.”; an exception ends with an error status and its stack in the panel. Errors thrown later by a setTimeout or a rejected promise are forwarded too, even after the initial run has completed, so a forgotten timer does not fail silently. The panel keeps a bounded buffer; a loop that logs on every tick cannot grow the panel without limit.

Stop discards the entire iframe, which also terminates its Worker, not just the current call. That is what makes a synchronous infinite loop interruptible: the editor and the page are on a different thread, so the Stop click is processed and the blocked Worker is killed. The next Run starts a fresh Worker, so variables and timers from the stopped run are gone. This is a deliberate trade between a reliable stop and persistent state.

Common uses

  • Language checks. Confirm coercion, array methods, optional chaining or a Date calculation without opening a project.
  • Reducing a bug. Paste the failing function, remove everything that does not reproduce the problem, and read the first error line.
  • Async experiments. Try top-level await, promise ordering or a timer without a build step.
  • Teaching and review. A ten-line snippet and its console output are easier to discuss than a repository.
  • Comparing implementations. Run two versions of a function on the same input and log both results.

Limits worth knowing

LimitWhyWorkaround
No Node APIs or npm installThe sandbox is a browser Worker, not NodeUse Worker-safe browser APIs; load a browser build from a CDN when needed
No visible DOM previewThis tool is a console runner, not an HTML rendererUse the HTML, CSS and JavaScript playground
No persistent variablesEach run is a new function body; Stop replaces the WorkerPut everything a run needs in the snippet
CORS appliesThe sandbox has an opaque originUse an API that sends Access-Control-Allow-Origin
No site storageSandboxed opaque origins generally cannot use localStorageKeep state in variables; use your own app for persistence

Privacy and cost

Pressing Run makes no network request by itself: the runner is a static page from this site and the snippet is passed through postMessage. If your code calls fetch or imports a URL, that request is yours and goes to the origin you named. The tool has no account, no analytics around the source, and no server-side execution path, so the code stays in the tab. That is also why the page starts instantly compared with the Python playground: the browser already has a JavaScript engine, so there is no runtime to download.

Frequently asked questions

Is my JavaScript uploaded anywhere?

No. The editor and the sandbox run in this browser tab. The page sends your source by postMessage to a sandboxed iframe on the same page; there is no endpoint that accepts code and nothing is stored on a server. The page itself makes no network request on your behalf when you press Run.

Can I use Node.js modules or npm packages?

No. The code runs in a Web Worker inside a sandboxed iframe, not Node: require(), fs, process and bare imports such as import lodash from "lodash" are unavailable. You can use Worker-safe browser APIs such as fetch, timers, crypto and TextEncoder, and import a full URL from a CDN with dynamic import() when that CDN allows CORS. A helper library that only needs to be a script can also be loaded through the HTML playground.

Can I access the page DOM or localStorage?

Not the parent page, and not any page at all. The code runs in a Web Worker created inside an iframe sandboxed without allow-same-origin; the origin is opaque, so it cannot read this site’s DOM, cookies or localStorage. A Worker has no DOM, so document is undefined here. Use the HTML, CSS and JavaScript playground when a visual result is the point.

Does top-level await work?

Yes. The source is evaluated as the body of an async function, so await can appear at the top level and a returned promise is awaited before the run is marked finished. Dynamic import() also works when the URL is reachable. Classic import declarations are not supported because the snippet is not parsed as a module.

What exactly appears in the output panel?

The sandbox mirrors console.log, console.info, console.warn and console.error, plus uncaught errors and unhandled promise rejections. Strings are printed as-is; other values are formatted, with objects serialised as JSON and circular references marked. The same messages still appear in the browser’s developer console, where objects stay expandable.

What happens if I write an infinite loop?

Press Stop. The code runs in a separate Worker inside a sandboxed iframe, so the page can discard the iframe and terminate the Worker even when the loop never yields; the editor stays responsive. Stopping also resets the sandbox: variables and timers from that run are gone, and the next Run starts from a fresh Worker.

Can I fetch an API?

Yes, with the same CORS rules as any browser page. The sandbox has an opaque origin, so the API must send Access-Control-Allow-Origin for the response to be readable. A request that succeeds in curl can still be blocked here, and that is a browser security boundary rather than a missing feature.

Is this a JavaScript REPL?

It is a script runner, not a line-by-line REPL. The last expression is not printed automatically; use console.log. Each run evaluates the snippet as a new function body, so top-level declarations do not carry over between runs. Timers or properties deliberately left on self can linger until Stop replaces the iframe, but relying on that is fragile — put everything a run needs in the snippet.

Sources

  • ECMAScript Language Specification — the language semantics the browser engine implements.
  • MDN Web Docs — JavaScript reference, async functions and dynamic import().
  • MDN Web Docs — iframe sandbox, the same-origin policy and CORS.
  • WHATWG HTML Standard — the sandbox attribute and the allow-scripts flag.

Everything runs in your browser — nothing you type is uploaded.