A Web Worker runs JavaScript in a separate execution context so suitable long-running work can proceed without blocking the page’s UI script. The page and worker communicate through messages: the worker cannot directly change the DOM, and moving work off the main thread is not a guaranteed speedup. This guide shows how to choose a worker, send data, handle results and errors, and avoid common loading and deployment failures.
What are Web Workers in JavaScript?
A Web Worker is a browser API for running a script in the background, independently of the page’s user-interface scripts. The WHATWG HTML Standard describes the purpose as allowing long-running scripts to continue independently of scripts responding to user interaction. That describes the execution model, not a guaranteed performance improvement for every task. WHATWG HTML Standard: Web workers
As an Amazon Associate I earn from qualifying purchases.
A useful mental model is two separate execution contexts connected by messages. The page sends input to the worker; the worker processes it and sends a result back; page code handles that result and, if needed, updates the DOM. MDN: Using Web Workers
Free tools Windows power users keep installed
One-click scans. No signup required.
Can a Web Worker access the DOM?
No. A worker cannot directly access the page’s DOM or the owning page’s Window. It runs in its own global context and can use JavaScript features and selected web APIs, but page changes must be performed by code in the page context after receiving a message. MDN: Web Workers API
#1 Best Overall
When should you use a Web Worker?
Consider a worker when a task takes meaningful time, can run independently of page objects, and can communicate through a defined input-and-result boundary. Examples may include computation or data processing that does not need to manipulate the DOM while it runs. A worker may be a poor fit for tiny tasks or work tightly coupled to page objects, because setting up communication and moving data also has costs. The cited documentation does not establish a benchmark threshold for deciding when the boundary pays off.
- Identify the work that is delaying interaction or rendering in the page’s UI execution path.
- Check whether the work can operate on data rather than DOM nodes or page-window objects.
- Estimate the payload and choose whether ordinary copying, ownership transfer, or—only for a specialized design—shared memory fits.
- Use a deliberately managed worker or bounded pool when parallel work is justified; workers are relatively heavyweight and should not be created in very large numbers. WHATWG HTML Standard: Web workers
Which kind of worker fits?
| Type | Scope and communication | Good fit |
|---|---|---|
| Dedicated worker | Owned by the script that creates it; communicates with that page through messages. | Page-specific computation or data processing; the usual starting point for moving suitable work off the page’s UI path. |
| Shared worker | Can be accessed by multiple same-origin scripts in different windows, frames, or other contexts; communication uses a MessagePort. |
Work or state that genuinely needs coordination across multiple contexts. It adds coordination complexity, and support history differs from dedicated workers. |
| Service worker | Has an application and network role, including request interception and support for offline experiences. | Network and application lifecycle tasks—not the default choice for moving a computation off the page’s main thread. |
Worker types are not interchangeable labels for background JavaScript. Check support for the particular type and the browser/device set you need to serve. MDN: Web Workers API WHATWG HTML Standard: Web workers
Rank #2
How do I use a Web Worker?
A dedicated worker can be created with new Worker(). The page sends a message, the worker handles its message event and posts a result, and the page handles that response. For bundled projects, MDN notes that webpack, Vite, and Parcel recommend resolving the worker URL relative to import.meta.url so the bundler can track and rename the asset. MDN: Using Web Workers
Page code
const worker = new Worker(new URL("./worker.js", import.meta.url), {
type: "module",
});
worker.addEventListener("message", (event) => {
// This handler runs in the page context, so it can update the DOM.
document.querySelector("#result").textContent = String(event.data);
});
worker.addEventListener("error", (event) => {
console.error("Worker failed:", event.message);
});
worker.postMessage({ operation: "square", value: 12 });
// When this page no longer needs the worker:
// worker.terminate();
Worker code in worker.js
self.addEventListener("message", (event) => {
const { operation, value } = event.data;
if (operation === "square" && typeof value === "number") {
self.postMessage(value * value);
return;
}
throw new Error("Unsupported operation or invalid input");
});
This example uses a module worker. If the task takes longer or accepts more varied input, define an explicit request/result shape and return expected failures as structured messages instead of letting the page infer them from console output. The worker’s error event and terminate() method are documented ways to report failures and stop a worker. MDN: Using Web Workers
How do I send data to a Web Worker?
Use postMessage() to send data and a message event handler to receive it. Ordinary message data is serialized and copied—commonly through structured cloning—so the worker does not receive a shared object reference to the page’s original object. This affects both semantics and the amount of work involved in sending large payloads. MDN: Web Workers API MDN: Using Web Workers
Choose between cloning, transferring, and shared memory
| Approach | What happens | When to consider it |
|---|---|---|
| Clone through a message | The message is serialized and copied; each context receives its own data rather than a shared object reference. | Ordinary structured input and results where a separate copy is suitable. |
| Transfer ownership | For supported transferable objects such as ArrayBuffer, a transfer list moves ownership instead of cloning the contents. The sender’s buffer is cleared and no longer usable. |
Large binary data when the sender can give up access to the transferred buffer. |
| Share memory | SharedArrayBuffer lets the page and worker work over shared memory rather than transferring that memory through messages. |
Advanced designs that need shared memory and can manage the associated coordination, determinism, security, and performance concerns. |
For example, an ArrayBuffer can be included in the transfer list as the second argument to postMessage(): worker.postMessage(buffer, [buffer]). After a successful transfer, treat the page’s original buffer as unusable. Shared memory is not a default optimization; it changes the synchronization and security considerations of the design. MDN: Using Web Workers
Rank #4
Classic or module worker?
| Worker mode | Loading and imports | Important behavior |
|---|---|---|
| Classic | Loads a worker script; can use importScripts(). |
Use when the worker is authored for classic-script loading. |
| Module | Create with new Worker(url, { type: "module" }); supports ECMAScript module imports. |
Uses module semantics, including strict mode by default and module-scoped top-level declarations. Static module dependencies load asynchronously using CORS, and worker module scripts require a JavaScript MIME type such as text/javascript. importScripts() fails in a module worker. |
Choose the mode to match how the worker and its dependencies are authored and served. A module worker is not just a classic worker with a different filename: its import and loading rules matter in deployment. WHATWG HTML Standard: Web workers MDN: Worker() constructor
Recommended Free Tools
What can prevent a worker from loading?
A correct message handler will not help if the browser cannot load the worker script. Check the URL, server response, policy, and—in module workers—dependency loading.
Best Value
- Origin and URL: The worker script URL must be same-origin with the creating document, or use an allowed
blob:ordata:URL, subject to applicable restrictions. MDN describes using an intermediate same-origin worker or a blob to address some cross-origin cases; those approaches still have constraints. - MIME type: Serve the worker script with the JavaScript media type expected by the browser. Module dependencies also need to meet the module loading rules.
- CORS: Module dependencies are fetched using CORS. When they are cross-origin, the server must permit those loads.
- Content Security Policy: The site’s CSP must allow the worker source through
worker-srcor the applicable fallback directives. - Untrusted URLs: Do not accept a worker URL from a user and execute it. MDN flags this as an XSS risk.
These checks are documented in MDN’s Worker() constructor reference.
How do I debug and clean up a worker?
Attach an error handler to the worker so failures are visible in the page, and terminate a worker when its work is no longer needed. MDN also documents using browser developer tools to inspect active worker scripts, set breakpoints, and add logpoints. MDN: Using Web Workers
- Confirm the worker script loaded from the intended URL and with the expected mode.
- Check the browser console and the worker’s error event for loading or runtime failures.
- Inspect message input and output at both ends of the boundary; verify that the payload can be serialized or transferred as intended.
- Use developer tools to debug the worker script itself, not only the page’s message handler.
- Call
worker.terminate()when the page no longer needs a dedicated worker; design any ongoing work lifecycle deliberately.
What browser support should you expect?
Support depends on the worker type and target browsers and devices. The WHATWG Edition for Web Developers updated October 6, 2026 lists the Worker interface as supported in current engines, while its shared-worker notes describe differences by engine and device, including a more limited mobile history. MDN likewise cautions that support varies by worker type. Check the specific type and browser/device targets your application serves rather than assuming all worker varieties are universally available. WHATWG HTML Standard: Web workers MDN: Worker() constructor
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




