Workers API (3)
Last updated Jun 25, 2026 let you run code at the edge. When you bind an R2 bucket to a Worker, you can read and write objects directly using the Workers API.
1. Create a bucket
A bucket stores your objects in R2. To create a new R2 bucket:
- Log in to your Cloudflare account:
sh
npx wrangler login
- Create a bucket named
my-bucket:
sh
npx wrangler r2 bucket create my-bucket
If prompted, select the account you want to create the bucket in. 3. Verify the bucket was created:
sh
npx wrangler r2 bucket list
- In the Cloudflare Dashboard, go to R2 object storage. Go to Overview ↗
- Select Create bucket.
- Enter a name for your bucket.
- Select a location for your bucket and a default storage class.
- Select Create bucket.
2. Create a Worker with an R2 binding
- Create a new Worker project:npmyarnpnpm
npm create cloudflare@latest -- r2-worker
yarn create cloudflare r2-worker
pnpm create cloudflare@latest r2-worker
When prompted, select Hello World example and JavaScript (or TypeScript) as your template. 2. Move into the project directory:
sh
cd r2-worker
- Add an R2 binding to your Wrangler configuration file. Replace
my-bucketwith your bucket name:
jsonc
{
"r2_buckets": [
{
"binding": "MY_BUCKET",
"bucket_name": "my-bucket"
}
]
}
toml
[[r2_buckets]]
binding = "MY_BUCKET"
bucket_name = "my-bucket"
- (Optional) If you are using TypeScript, regenerate types:
sh
npx wrangler types
3. Read and write objects
Use the binding to interact with your bucket. This example stores and retrieves objects based on the URL path:
src/index.jsjs
export default {
async fetch(request, env) {
// Get the object key from the URL path
// For example: /images/cat.png → images/cat.png
const url = new URL(request.url);
const key = url.pathname.slice(1);
// PUT: Store the request body in R2
if (request.method === "PUT") {
await env.MY_BUCKET.put(key, request.body);
return new Response(`Put ${key} successfully!`);
}
// GET: Retrieve the object from R2
const object = await env.MY_BUCKET.get(key);
if (object === null) {
return new Response("Object not found", { status: 404 });
}
return new Response(object.body);
},
};
src/index.tsts
export default {
async fetch(request, env): Promise<Response> {
// Get the object key from the URL path
// For example: /images/cat.png → images/cat.png
const url = new URL(request.url);
const key = url.pathname.slice(1);
// PUT: Store the request body in R2
if (request.method === "PUT") {
await env.MY_BUCKET.put(key, request.body);
return new Response(`Put ${key} successfully!`);
}
// GET: Retrieve the object from R2
const object = await env.MY_BUCKET.get(key);
if (object === null) {
return new Response("Object not found", { status: 404 });
}
return new Response(object.body);
},
} satisfies ExportedHandler<Env>;
4. Test and deploy
- Test your Worker locally:
sh
npx wrangler dev
Local development
By default, wrangler dev uses a local R2 simulation. Objects you store during development exist only on your machine in the .wrangler/state folder and do not affect your production bucket.
To connect to your real R2 bucket during development, add "remote": true to your R2 binding in your Wrangler configuration file. Refer to remote bindings for more information.
2. Once the dev server is running, test storing and retrieving objects:
```sh # Store an object curl -X PUT http://localhost:8787/my-file.txt -d 'Hello, R2!'
# Retrieve the object curl http://localhost:8787/my-file.txt ```
- Deploy to production:
sh
npx wrangler deploy
- After deploying, Wrangler outputs your Worker's URL (for example,
https://r2-worker.<YOUR_SUBDOMAIN>.workers.dev). Test storing and retrieving objects:
```sh
# Store an object
curl -X PUT https://r2-worker.
# Retrieve the object
curl https://r2-worker.
Refer to the Workers R2 API documentation for the complete API reference.
Next steps
Presigned URLs
Generate temporary URLs for private object access.
Public buckets
Serve files directly over HTTP with a public bucket.
CORS
Configure CORS for browser-based uploads.
Object lifecycles
Set up lifecycle rules to automatically delete old objects.
Was this helpful?
YesNo
On this page
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/r2/get-started/workers-api/#page","headline":"Workers API","description":"Use R2 from Cloudflare Workers with the Workers API.","url":"https://developers.cloudflare.com/r2/get-started/workers-api/","inLanguage":"en","image":"https://developers.cloudflare.com/r2/get-started/workers-api/og.png?v=5497e0b0b68f0765","dateModified":"2026-06-25","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
description: Find out how R2 works. title: How R2 works image: https://developers.cloudflare.com/r2/how-r2-works/og.png?v=780a17982623cb3c
Documentation Index
Fetch the complete documentation index at: https://developers.cloudflare.com/r2/llms.txt
Use this file to discover all available pages before exploring further.
Docs