Cloudflare Workers let you run JavaScript, WebAssembly, or other languages compiled to Wasm, directly on Cloudflare’s edge network.

Let’s get a simple "Hello, World!" Worker up and running.

First, you need an account with Cloudflare. If you don’t have one, sign up at cloudflare.com.

Next, you’ll need the wrangler CLI tool, Cloudflare’s command-line interface for building and deploying Workers. Install it with npm:

npm install -g wrangler

Now, let’s create a new Worker project. Navigate to a directory where you want to store your projects and run:

wrangler generate my-first-worker

This will create a new directory named my-first-worker with a basic project structure. The most important files are:

  • wrangler.toml: The configuration file for your Worker.
  • src/index.js: The main JavaScript file for your Worker.

Open src/index.js. You’ll see something like this:

/**
 * @typedef {import('cloudflare-workers-types').Request} Request
 * @typedef {import('cloudflare-workers-types').Env} Env
 */

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
})

/**
 * Respond to the request
 * @param {Request} request
 * @returns {Promise<Response>}
 */
async function handleRequest(request) {
  return new Response('Hello worker!', {
    headers: { 'content-type': 'text/plain' },
  })
}

This is the core of your Worker. The addEventListener('fetch', ...) line tells Cloudflare to run the handleRequest function every time a request hits your Worker. The handleRequest function receives the incoming Request object and must return a Response object.

Before deploying, you need to configure wrangler.toml. Open the file and you’ll see a basic structure. For a simple Worker, you might not need much, but you’ll need to specify your account ID. You can find your account ID on the Cloudflare dashboard, usually in the top-right corner of the overview page.

Here’s an example wrangler.toml:

name = "my-first-worker"
main = "src/index.js"
compatibility_date = "2023-10-26" # Use a recent date
account_id = "YOUR_ACCOUNT_ID_HERE"

Replace "YOUR_ACCOUNT_ID_HERE" with your actual Cloudflare Account ID. The compatibility_date is important; it determines which Cloudflare features and APIs your Worker is compatible with. Using a recent date generally gives you access to the latest features.

Now, let’s preview your Worker locally. This is incredibly useful for testing without deploying. Run:

wrangler dev

This command will start a local development server. It will give you a URL (usually http://127.0.0.1:8787) that you can use to test your Worker. Open this URL in your browser, and you should see "Hello worker!".

To deploy your Worker to Cloudflare’s edge network, run:

wrangler publish

This command uploads your Worker code and configuration to Cloudflare. Once published, wrangler will output a URL where your Worker is accessible. It will typically be a subdomain of workers.dev. For example, it might look like my-first-worker.your-subdomain.workers.dev. Visit this URL in your browser, and you’ll see "Hello worker!" again, this time served from Cloudflare’s edge.

You can also associate your Worker with a custom domain you manage through Cloudflare. This is done within the wrangler.toml file by adding a routes section. For instance, to have your Worker respond to requests to your-domain.com/api/*:

name = "my-first-worker"
main = "src/index.js"
compatibility_date = "2023-10-26"
account_id = "YOUR_ACCOUNT_ID_HERE"

[[routes]]
pattern = "your-domain.com/api/*"
zone_name = "your-domain.com"

Make sure your-domain.com is added to your Cloudflare account and has its DNS managed by Cloudflare. After publishing with this configuration, requests to your-domain.com/api/any/path will be handled by your Worker.

A subtle but powerful aspect of Workers is that they don’t just run JavaScript; they are designed to intercept and respond to HTTP requests before they even reach your origin server. This means you can use them for a wide range of tasks: serving static assets, performing A/B testing, authenticating users, modifying request headers, or even completely replacing your backend for certain routes. The event.respondWith() pattern is key here – your Worker provides the response, short-circuiting the normal request flow.

The primary mechanism for interacting with the outside world from a Worker is the fetch API. You can use fetch to make outgoing HTTP requests to other services, including your own origin servers, external APIs, or even other Workers. This allows you to build complex applications that orchestrate requests and responses across multiple endpoints.

If you want to make your Worker dynamically respond based on the incoming request, you can inspect the request object. For example, to read a query parameter:

async function handleRequest(request) {
  const url = new URL(request.url);
  const name = url.searchParams.get('name');
  if (name) {
    return new Response(`Hello, ${name}!`, {
      headers: { 'content-type': 'text/plain' },
    });
  }
  return new Response('Hello worker!', {
    headers: { 'content-type': 'text/plain' },
  });
}

Now, visiting http://your-worker-url.workers.dev/?name=Alice will greet you with "Hello, Alice!".

The next step is often to manage state across multiple requests or users, which leads to exploring Workers KV (Key-Value) storage or Durable Objects for more sophisticated data management.

Want structured learning?

Take the full Cloudflare course →