---
title: Request · Cloudflare Workers docs
description: Interface that represents an HTTP request.
lastUpdated: 2025-10-06T16:04:10.000Z
chatbotDeprioritize: false
source_url:
  html: https://developers.cloudflare.com/workers/runtime-apis/request/
  md: https://developers.cloudflare.com/workers/runtime-apis/request/index.md
---

The [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request/Request) interface represents an HTTP request and is part of the [Fetch API](https://developers.cloudflare.com/workers/runtime-apis/fetch/).

## Background

The most common way you will encounter a `Request` object is as a property of an incoming request:

```js
export default {
  async fetch(request, env, ctx) {
    return new Response('Hello World!');
  },
};
```

You may also want to construct a `Request` yourself when you need to modify a request object, because the incoming `request` parameter that you receive from the [`fetch()` handler](https://developers.cloudflare.com/workers/runtime-apis/handlers/fetch/) is immutable.

```js
export default {
  async fetch(request, env, ctx) {
        const url = "https://example.com";
        const modifiedRequest = new Request(url, request);
    // ...
  },
};
```

The [`fetch() handler`](https://developers.cloudflare.com/workers/runtime-apis/handlers/fetch/) invokes the `Request` constructor. The [`RequestInit`](#options) and [`RequestInitCfProperties`](#the-cf-property-requestinitcfproperties) types defined below also describe the valid parameters that can be passed to the [`fetch() handler`](https://developers.cloudflare.com/workers/runtime-apis/handlers/fetch/).

***

## Constructor

```js
let request = new Request(input, options)
```

### Parameters

* `input` string | Request

  * Either a string that contains a URL, or an existing `Request` object.

* `options` options optional

  * Optional options object that contains settings to apply to the `Request`.

#### `options`

An object containing properties that you want to apply to the request.

* `cache` `undefined | 'no-store' | 'no-cache'` optional

  * Standard HTTP `cache` header. Only `cache: 'no-store'` and `cache: 'no-cache'` are supported. Any other cache header will result in a `TypeError` with the message `Unsupported cache mode: <attempted-cache-mode>`.

* `cf` RequestInitCfProperties optional

  * Cloudflare-specific properties that can be set on the `Request` that control how Cloudflare’s global network handles the request.

* `method` string optional

  * The HTTP request method. The default is `GET`. In Workers, all [HTTP request methods](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Methods) are supported, except for [`CONNECT`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Methods/CONNECT).

* `headers` Headers optional

  * A [`Headers` object](https://developer.mozilla.org/en-US/docs/Web/API/Headers).

* `body` string | ReadableStream | FormData | URLSearchParams optional

  * The request body, if any.
  * Note that a request using the GET or HEAD method cannot have a body.

* `redirect` string optional

  * The redirect mode to use: `follow`, `error`, or `manual`. The default for a new `Request` object is `follow`. Note, however, that the incoming `Request` property of a `FetchEvent` will have redirect mode `manual`.

* `signal` AbortSignal optional

  * If provided, the request can be canceled by triggering an abort on the corresponding `AbortController`.

#### The `cf` property (`RequestInitCfProperties`)

An object containing Cloudflare-specific properties that can be set on the `Request` object. For example:

```js
// Disable ScrapeShield for this request.
fetch(event.request, { cf: { scrapeShield: false } })
```

Invalid or incorrectly-named keys in the `cf` object will be silently ignored. Consider using TypeScript and generating types by running [`wrangler types`](https://developers.cloudflare.com/workers/languages/typescript/#generate-types) to ensure proper use of the `cf` object.

* `apps` boolean optional

  * Whether [Cloudflare Apps](https://www.cloudflare.com/apps/) should be enabled for this request. Defaults to `true`.

* `cacheEverything` boolean optional

  * Treats all content as static and caches all [file types](https://developers.cloudflare.com/cache/concepts/default-cache-behavior#default-cached-file-extensions) beyond the Cloudflare default cached content. Respects cache headers from the origin web server. This is equivalent to setting the Page Rule [**Cache Level** (to **Cache Everything**)](https://developers.cloudflare.com/rules/page-rules/reference/settings/). Defaults to `false`. This option applies to `GET` and `HEAD` request methods only.

* `cacheKey` string optional

  * A request’s cache key is what determines if two requests are the same for caching purposes. If a request has the same cache key as some previous request, then Cloudflare can serve the same cached response for both.

* `cacheTags` Array\<string> optional

  * This option appends additional [**Cache-Tag**](https://developers.cloudflare.com/cache/how-to/purge-cache/purge-by-tags/) headers to the response from the origin server. This allows for purges of cached content based on tags provided by the Worker, without modifications to the origin server. This is performed using the [**Purge by Tag**](https://developers.cloudflare.com/cache/how-to/purge-cache/purge-by-tags/#purge-using-cache-tags) feature.

* `cacheTtl` number optional

  * This option forces Cloudflare to cache the response for this request, regardless of what headers are seen on the response. This is equivalent to setting two Page Rules: [**Edge Cache TTL**](https://developers.cloudflare.com/cache/how-to/edge-browser-cache-ttl/) and [**Cache Level** (to **Cache Everything**)](https://developers.cloudflare.com/rules/page-rules/reference/settings/). The value must be zero or a positive number. A value of `0` indicates that the cache asset expires immediately. This option applies to `GET` and `HEAD` request methods only.

* `cacheTtlByStatus` `{ [key: string]: number }` optional

  * This option is a version of the `cacheTtl` feature which chooses a TTL based on the response’s status code. If the response to this request has a status code that matches, Cloudflare will cache for the instructed time and override cache instructives sent by the origin. For example: `{ "200-299": 86400, "404": 1, "500-599": 0 }`. The value can be any integer, including zero and negative integers. A value of `0` indicates that the cache asset expires immediately. Any negative value instructs Cloudflare not to cache at all. This option applies to `GET` and `HEAD` request methods only.

* `image` Object | null optional

  * Enables [Image Resizing](https://developers.cloudflare.com/images/transform-images/) for this request. The possible values are described in [Transform images via Workers](https://developers.cloudflare.com/images/transform-images/transform-via-workers/) documentation.

* `mirage` boolean optional

  * Whether [Mirage](https://www.cloudflare.com/website-optimization/mirage/) (deprecated) should be enabled for this request, if otherwise configured for this zone. Defaults to `true`.

* `polish` string optional

  * Sets [Polish](https://blog.cloudflare.com/introducing-polish-automatic-image-optimizati/) mode. The possible values are `lossy`, `lossless` or `off`.

* `resolveOverride` string optional

  * Directs the request to an alternate origin server by overriding the DNS lookup. The value of `resolveOverride` specifies an alternate hostname which will be used when determining the origin IP address, instead of using the hostname specified in the URL. The `Host` header of the request will still match what is in the URL. Thus, `resolveOverride` allows a request to be sent to a different server than the URL / `Host` header specifies. However, `resolveOverride` will only take effect if both the URL host and the host specified by `resolveOverride` are within your zone. If either specifies a host from a different zone / domain, then the option will be ignored for security reasons. If you need to direct a request to a host outside your zone (while keeping the `Host` header pointing within your zone), first create a CNAME record within your zone pointing to the outside host, and then set `resolveOverride` to point at the CNAME record. Note that, for security reasons, it is not possible to set the `Host` header to specify a host outside of your zone unless the request is actually being sent to that host.

* `scrapeShield` boolean optional

  * Whether [ScrapeShield](https://blog.cloudflare.com/introducing-scrapeshield-discover-defend-dete/) should be enabled for this request, if otherwise configured for this zone. Defaults to `true`.

* `webp` boolean optional

  * Enables or disables [WebP](https://blog.cloudflare.com/a-very-webp-new-year-from-cloudflare/) image format in [Polish](https://developers.cloudflare.com/images/polish/).

***

## Properties

All properties of an incoming `Request` object (the request you receive from the [`fetch()` handler](https://developers.cloudflare.com/workers/runtime-apis/handlers/fetch/)) are read-only. To modify the properties of an incoming request, create a new `Request` object and pass the options to modify to its [constructor](#constructor).

* `body` ReadableStream read-only

  * Stream of the body contents.

* `bodyUsed` Boolean read-only

  * Declares whether the body has been used in a response yet.

* `cf` IncomingRequestCfProperties read-only

  * An object containing properties about the incoming request provided by Cloudflare’s global network.
  * This property is read-only (unless created from an existing `Request`). To modify its values, pass in the new values on the [`cf` key of the `init` options argument](https://developers.cloudflare.com/workers/runtime-apis/request/#the-cf-property-requestinitcfproperties) when creating a new `Request` object.

* `headers` Headers read-only

  * A [`Headers` object](https://developer.mozilla.org/en-US/docs/Web/API/Headers).

  * Compared to browsers, Cloudflare Workers imposes very few restrictions on what headers you are allowed to send. For example, a browser will not allow you to set the `Cookie` header, since the browser is responsible for handling cookies itself. Workers, however, has no special understanding of cookies, and treats the `Cookie` header like any other header.

  Warning

  If the response is a redirect and the redirect mode is set to `follow` (see below), then all headers will be forwarded to the redirect destination, even if the destination is a different hostname or domain. This includes sensitive headers like `Cookie`, `Authorization`, or any application-specific headers. If this is not the behavior you want, you should set redirect mode to `manual` and implement your own redirect policy. Note that redirect mode defaults to `manual` for requests that originated from the Worker's client, so this warning only applies to `fetch()`es made by a Worker that are not proxying the original request.

* `method` string read-only

  * Contains the request’s method, for example, `GET`, `POST`, etc.

* `redirect` string read-only

  * The redirect mode to use: `follow`, `error`, or `manual`. The `fetch` method will automatically follow redirects if the redirect mode is set to `follow`. If set to `manual`, the `3xx` redirect response will be returned to the caller as-is. The default for a new `Request` object is `follow`. Note, however, that the incoming `Request` property of a `FetchEvent` will have redirect mode `manual`.

* `signal` AbortSignal read-only

  * The `AbortSignal` corresponding to this request. If you use the [`enable_request_signal`](https://developers.cloudflare.com/workers/configuration/compatibility-flags/#enable-requestsignal-for-incoming-requests) compatibility flag, you can attach an event listener to the signal. This allows you to perform cleanup tasks or write to logs before your Worker's invocation ends. For example, if you run the Worker below, and then abort the request from the client, a log will be written:

    * JavaScript

      ```js
      export default {
        async fetch(request, env, ctx) {
          // This sets up an event listener that will be called if the client disconnects from your
          // worker.
          request.signal.addEventListener("abort", () => {
            console.log("The request was aborted!");
          });


          const { readable, writable } = new IdentityTransformStream();
          sendPing(writable);
          return new Response(readable, {
            headers: { "Content-Type": "text/plain" },
          });
        },
      };


      async function sendPing(writable) {
        const writer = writable.getWriter();
        const enc = new TextEncoder();


        for (;;) {
          // Send 'ping' every second to keep the connection alive
          await writer.write(enc.encode("ping\r\n"));
          await scheduler.wait(1000);
        }
      }
      ```

    * TypeScript

      ```ts
      export default {
        async fetch(request, env, ctx): Promise<Response> {
          // This sets up an event listener that will be called if the client disconnects from your
          // worker.
          request.signal.addEventListener('abort', () => {
            console.log('The request was aborted!');
          });


          const { readable, writable } = new IdentityTransformStream();
          sendPing(writable);
          return new Response(readable, { headers: { 'Content-Type': 'text/plain' } });
        },
      } satisfies ExportedHandler<Env>;


      async function sendPing(writable: WritableStream): Promise<void> {
        const writer = writable.getWriter();
        const enc = new TextEncoder();


        for (;;) {
          // Send 'ping' every second to keep the connection alive
          await writer.write(enc.encode('ping\r\n'));
          await scheduler.wait(1000);
        }
      }
      ```

* `url` string read-only

  * Contains the URL of the request.

### `IncomingRequestCfProperties`

In addition to the properties on the standard [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) object, the `request.cf` object on an inbound `Request` contains information about the request provided by Cloudflare’s global network.

All plans have access to:

* `asn` Number

  * ASN of the incoming request, for example, `395747`.

* `asOrganization` string

  * The organization which owns the ASN of the incoming request, for example, `Google Cloud`.

* `botManagement` Object | null

  * Only set when using Cloudflare Bot Management. Object with the following properties: `score`, `verifiedBot`, `staticResource`, `ja3Hash`, `ja4`, and `detectionIds`. Refer to [Bot Management Variables](https://developers.cloudflare.com/bots/reference/bot-management-variables/) for more details.

* `clientAcceptEncoding` string | null

  * If Cloudflare replaces the value of the `Accept-Encoding` header, the original value is stored in the `clientAcceptEncoding` property, for example, `"gzip, deflate, br"`.

* `colo` string

  * The three-letter [`IATA`](https://en.wikipedia.org/wiki/IATA_airport_code) airport code of the data center that the request hit, for example, `"DFW"`.

* `country` string | null

  * Country of the incoming request. The two-letter country code in the request. This is the same value as that provided in the `CF-IPCountry` header, for example, `"US"`.

* `isEUCountry` string | null

  * If the country of the incoming request is in the EU, this will return `"1"`. Otherwise, this property is either omitted or `false`.

* `httpProtocol` string

  * HTTP Protocol, for example, `"HTTP/2"`.

* `hostMetadata` Object | undefined

  * Only populated when the incoming request is from a zone with custom hostname metadata. Refer to the Cloudflare for Platforms documentation for more about what you can add as [custom hostname metadata](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/custom-metadata/), and how it is exposed on the `hostMetadata` field.

* `requestPriority` string | null

  * The browser-requested prioritization information in the request object, for example, `"weight=192;exclusive=0;group=3;group-weight=127"`.

* `tlsCipher` string

  * The cipher for the connection to Cloudflare, for example, `"AEAD-AES128-GCM-SHA256"`.

* `tlsClientAuth` Object | null

  * Only set when using Cloudflare Access or API Shield (mTLS). Object with the following properties: `certFingerprintSHA1`, `certFingerprintSHA256`, `certIssuerDN`, `certIssuerDNLegacy`, `certIssuerDNRFC2253`, `certIssuerSKI`, `certIssuerSerial`, `certNotAfter`, `certNotBefore`, `certPresented`, `certRevoked`, `certSKI`, `certSerial`, `certSubjectDN`, `certSubjectDNLegacy`, `certSubjectDNRFC2253`, `certVerified`.

* `tlsClientCiphersSha1` string

  * The SHA-1 hash (Base64-encoded) of the cipher suite sent by the client during the TLS handshake, encoded in big-endian format. For example, `"GXSPDLP4G3X+prK73a4wBuOaHRc="`.

* `tlsClientExtensionsSha1` string

  * The SHA-1 hash (Base64-encoded) of the TLS client extensions sent during the handshake, encoded in big-endian format. For example, `"OWFiM2I5ZDc0YWI0YWYzZmFkMGU0ZjhlYjhiYmVkMjgxNTU5YTU2Mg=="`.

* `tlsClientExtensionsSha1Le` string

  * The SHA-1 hash (Base64-encoded) of the TLS client extensions sent during the handshake, encoded in little-endian format. For example, `"7zIpdDU5pvFPPBI2/PCzqbaXnRA="`.

* `tlsClientHelloLength` string

  * The length of the client hello message sent in a [TLS handshake](https://www.cloudflare.com/learning/ssl/what-happens-in-a-tls-handshake/). For example, `"508"`. Specifically, the length of the bytestring of the client hello.

* `tlsClientRandom` string

  * The value of the 32-byte random value provided by the client in a [TLS handshake](https://www.cloudflare.com/learning/ssl/what-happens-in-a-tls-handshake/). Refer to [RFC 8446](https://datatracker.ietf.org/doc/html/rfc8446#section-4.1.2) for more details.

* `tlsVersion` string

  * The TLS version of the connection to Cloudflare, for example, `TLSv1.3`.

* `city` string | null

  * City of the incoming request, for example, `"Austin"`.

* `continent` string | null

  * Continent of the incoming request, for example, `"NA"`.

* `latitude` string | null

  * Latitude of the incoming request, for example, `"30.27130"`.

* `longitude` string | null

  * Longitude of the incoming request, for example, `"-97.74260"`.

* `postalCode` string | null

  * Postal code of the incoming request, for example, `"78701"`.

* `metroCode` string | null

  * Metro code (DMA) of the incoming request, for example, `"635"`.

* `region` string | null

  * If known, the [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) name for the first level region associated with the IP address of the incoming request, for example, `"Texas"`.

* `regionCode` string | null

  * If known, the [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) code for the first-level region associated with the IP address of the incoming request, for example, `"TX"`.

* `timezone` string

  * Timezone of the incoming request, for example, `"America/Chicago"`.

Warning

The `request.cf` object is not available in the Cloudflare Workers dashboard or Playground preview editor.

***

## Methods

### Instance methods

These methods are only available on an instance of a `Request` object or through its prototype.

* `clone()` : Request

  * Creates a copy of the `Request` object.

* `arrayBuffer()` : Promise\<ArrayBuffer>

  * Returns a promise that resolves with an [`ArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer) representation of the request body.

* `formData()` : Promise\<FormData>

  * Returns a promise that resolves with a [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) representation of the request body.

* `json()` : Promise\<Object>

  * Returns a promise that resolves with a JSON representation of the request body.

* `text()` : Promise\<string>

  * Returns a promise that resolves with a string (text) representation of the request body.

***

## The `Request` context

Each time a Worker is invoked by an incoming HTTP request, the [`fetch()` handler](https://developers.cloudflare.com/workers/runtime-apis/handlers/fetch) is called on your Worker. The `Request` context starts when the `fetch()` handler is called, and asynchronous tasks (such as making a subrequest using the [`fetch() API`](https://developers.cloudflare.com/workers/runtime-apis/fetch/)) can only be run inside the `Request` context:

```js
export default {
  async fetch(request, env, ctx) {
        // Request context starts here
    return new Response('Hello World!');
  },
};
```

### When passing a promise to fetch event `.respondWith()`

If you pass a Response promise to the fetch event `.respondWith()` method, the request context is active during any asynchronous tasks which run before the Response promise has settled. You can pass the event to an async handler, for example:

```js
addEventListener("fetch", event => {
  event.respondWith(eventHandler(event))
})


// No request context available here


async function eventHandler(event){
  // Request context available here
  return new Response("Hello, Workers!")
}
```

### Errors when attempting to access an inactive `Request` context

Any attempt to use APIs such as `fetch()` or access the `Request` context during script startup will throw an exception:

```js
const promise = fetch("https://example.com/") // Error
async function eventHandler(event){..}
```

This code snippet will throw during script startup, and the `"fetch"` event listener will never be registered.

***

### Set the `Content-Length` header

The `Content-Length` header will be automatically set by the runtime based on whatever the data source for the `Request` is. Any value manually set by user code in the `Headers` will be ignored. To have a `Content-Length` header with a specific value specified, the `body` of the `Request` must be either a `FixedLengthStream` or a fixed-length value just as a string or `TypedArray`.

A `FixedLengthStream` is an identity `TransformStream` that permits only a fixed number of bytes to be written to it.

```js
  const { writable, readable } = new FixedLengthStream(11);


  const enc = new TextEncoder();
  const writer = writable.getWriter();
  writer.write(enc.encode("hello world"));
  writer.end();


  const req = new Request('https://example.org', { method: 'POST', body: readable });
```

Using any other type of `ReadableStream` as the body of a request will result in Chunked-Encoding being used.

***

## Related resources

* [Examples: Modify request property](https://developers.cloudflare.com/workers/examples/modify-request-property/)
* [Examples: Accessing the `cf` object](https://developers.cloudflare.com/workers/examples/accessing-the-cloudflare-object/)
* [Reference: `Response`](https://developers.cloudflare.com/workers/runtime-apis/response/)
* Write your Worker code in [ES modules syntax](https://developers.cloudflare.com/workers/reference/migrate-to-module-workers/) for an optimized experience.
