[{"data":1,"prerenderedAt":48},["ShallowReactive",2],{"\u002Fcloudflare-config\u002Fr2":3},{"title":4,"description":5,"path":6,"date":7,"updated":8,"verified":7,"category":9,"keywords":10,"officialSources":16,"related":26,"readingTime":30,"html":31,"toc":32},"R2 bindings in cloudflare.config.ts","Reference an R2 bucket with bindings.r2 and access it through your Worker environment. A binding does not make the bucket publicly accessible.","\u002Fcloudflare-config\u002Fr2","2026-09-29","2026-09-30","Configuration",[11,12,13,14,15],"cloudflare.config.ts r2","cloudflare r2 config example","cf r2 bucket","r2 binding cloudflare.config.ts","bindings.r2",[17,20,23],{"label":18,"url":19},"Cloudflare configuration types and helpers","https:\u002F\u002Fgithub.com\u002Fcloudflare\u002Fworkers-sdk\u002Ftree\u002Fmain\u002Fpackages\u002Fconfig\u002Fsrc",{"label":21,"url":22},"cf CLI source and README","https:\u002F\u002Fgithub.com\u002Fcloudflare\u002Fcf\u002Ftree\u002Fmain\u002Fpackages\u002Fcli",{"label":24,"url":25},"Use R2 from Workers","https:\u002F\u002Fdevelopers.cloudflare.com\u002Fr2\u002Fapi\u002Fworkers\u002Fworkers-api-usage\u002F",[27,28,29],"\u002Fcloudflare-config","\u002Fcloudflare-config\u002Fd1","\u002Fcf-deploy",2,"\u003Ch2 id=\"quick-configuration\">Quick configuration\u003C\u002Fh2>\n\u003Cdiv class=\"code-block\">\u003Cdiv class=\"code-toolbar\">\u003Cspan>cloudflare.config.ts\u003C\u002Fspan>\u003Cbutton type=\"button\" data-copy-code aria-label=\"Copy code\">Copy\u003C\u002Fbutton>\u003C\u002Fdiv>\u003Cpre>\u003Ccode class=\"hljs language-ts\">\u003Cspan class=\"hljs-keyword\">import\u003C\u002Fspan> { bindings, defineConfig } \u003Cspan class=\"hljs-keyword\">from\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&quot;cf\u002Fconfig&quot;\u003C\u002Fspan>;\n\n\u003Cspan class=\"hljs-keyword\">export\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">default\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">defineConfig\u003C\u002Fspan>({\n  \u003Cspan class=\"hljs-attr\">worker\u003C\u002Fspan>: {\n    \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&quot;uploads-worker&quot;\u003C\u002Fspan>,\n    \u003Cspan class=\"hljs-attr\">compatibilityDate\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&quot;2026-09-29&quot;\u003C\u002Fspan>,\n    \u003Cspan class=\"hljs-attr\">entrypoint\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&quot;.\u002Fsrc\u002Findex.ts&quot;\u003C\u002Fspan>,\n    \u003Cspan class=\"hljs-attr\">env\u003C\u002Fspan>: {\n      \u003Cspan class=\"hljs-attr\">UPLOADS\u003C\u002Fspan>: bindings.\u003Cspan class=\"hljs-title function_\">r2\u003C\u002Fspan>({ \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&quot;notes-uploads&quot;\u003C\u002Fspan> }),\n    },\n  },\n});\n\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fdiv>\u003Cp>\u003Ccode>UPLOADS\u003C\u002Fcode> becomes the binding on the Worker environment. The \u003Ccode>name\u003C\u002Fcode> option selects the bucket. The helper supports a bucket name, not the Wrangler field name \u003Ccode>bucket_name\u003C\u002Fcode>.\u003C\u002Fp>\n\u003Ch2 id=\"create-the-bucket\">Create the bucket\u003C\u002Fh2>\n\u003Cdiv class=\"code-block\">\u003Cdiv class=\"code-toolbar\">\u003Cspan>Terminal\u003C\u002Fspan>\u003Cbutton type=\"button\" data-copy-code aria-label=\"Copy code\">Copy\u003C\u002Fbutton>\u003C\u002Fdiv>\u003Cpre>\u003Ccode class=\"hljs language-bash\">\u003Cspan class=\"hljs-comment\"># Inspect the operation before creating a remote bucket\u003C\u002Fspan>\ncf r2 buckets create --\u003Cspan class=\"hljs-built_in\">help\u003C\u002Fspan>\n\n\u003Cspan class=\"hljs-comment\"># Authenticated operation; creates an account resource\u003C\u002Fspan>\ncf r2 buckets create --name notes-uploads\n\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fdiv>\u003Cp>Confirm the account and bucket jurisdiction. If your bucket belongs to a jurisdiction, the binding’s \u003Ccode>jurisdiction\u003C\u002Fcode> must match the resource you intend to use. Keep resource names distinct between staging and production when data must remain separate.\u003C\u002Fp>\n\u003Ch2 id=\"read-an-object-in-a-worker\">Read an object in a Worker\u003C\u002Fh2>\n\u003Cdiv class=\"code-block\">\u003Cdiv class=\"code-toolbar\">\u003Cspan>src\u002Findex.ts\u003C\u002Fspan>\u003Cbutton type=\"button\" data-copy-code aria-label=\"Copy code\">Copy\u003C\u002Fbutton>\u003C\u002Fdiv>\u003Cpre>\u003Ccode class=\"hljs language-ts\">\u003Cspan class=\"hljs-keyword\">export\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">default\u003C\u002Fspan> {\n  \u003Cspan class=\"hljs-keyword\">async\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">fetch\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">\u003Cspan class=\"hljs-attr\">_request\u003C\u002Fspan>: \u003Cspan class=\"hljs-title class_\">Request\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">env\u003C\u002Fspan>: { UPLOADS: R2Bucket }\u003C\u002Fspan>) {\n    \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-built_in\">object\u003C\u002Fspan> = \u003Cspan class=\"hljs-keyword\">await\u003C\u002Fspan> env.\u003Cspan class=\"hljs-property\">UPLOADS\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">get\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&quot;hello.txt&quot;\u003C\u002Fspan>);\n    \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!\u003Cspan class=\"hljs-built_in\">object\u003C\u002Fspan>) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">Response\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&quot;Not found&quot;\u003C\u002Fspan>, { \u003Cspan class=\"hljs-attr\">status\u003C\u002Fspan>: \u003Cspan class=\"hljs-number\">404\u003C\u002Fspan> });\n\n    \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> headers = \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">Headers\u003C\u002Fspan>();\n    \u003Cspan class=\"hljs-built_in\">object\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">writeHttpMetadata\u003C\u002Fspan>(headers);\n    headers.\u003Cspan class=\"hljs-title function_\">set\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&quot;etag&quot;\u003C\u002Fspan>, \u003Cspan class=\"hljs-built_in\">object\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">httpEtag\u003C\u002Fspan>);\n    \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">Response\u003C\u002Fspan>(\u003Cspan class=\"hljs-built_in\">object\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">body\u003C\u002Fspan>, { headers });\n  },\n};\n\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fdiv>\u003Cp>Generate the Cloudflare runtime types in your Worker project so \u003Ccode>R2Bucket\u003C\u002Fcode> is available to TypeScript. This example reads a fixed key; it is not an upload endpoint or an authorization policy.\u003C\u002Fp>\n\u003Cp>An R2 binding gives Worker code access to a bucket. Public delivery through a custom domain or an r2.dev endpoint is a separate configuration decision. Do not infer public accessibility from the presence of the binding.\u003C\u002Fp>\n\u003Ch2 id=\"from-wrangler-configuration\">From Wrangler configuration\u003C\u002Fh2>\n\u003Cp>The Wrangler \u003Ccode>r2_buckets\u003C\u002Fcode> array uses \u003Ccode>binding\u003C\u002Fcode> and \u003Ccode>bucket_name\u003C\u002Fcode>. In the new config, \u003Ccode>worker.env.UPLOADS\u003C\u002Fcode> supplies the binding name and \u003Ccode>bindings.r2({ name: ... })\u003C\u002Fcode> carries the bucket reference.\u003C\u002Fp>\n\u003Cp>Use \u003Ca href=\"\u002Fwrangler-to-cf\">the official migration\u003C\u002Fa> for existing configuration, then check bucket names and jurisdiction rather than replacing fields mechanically.\u003C\u002Fp>\n\u003Ch2 id=\"common-mistakes\">Common mistakes\u003C\u002Fh2>\n\u003Cul>\n\u003Cli>Using a bucket ID where the helper expects a name.\u003C\u002Fli>\n\u003Cli>Reading from a local simulation and expecting remote objects to appear.\u003C\u002Fli>\n\u003Cli>Assuming a binding automatically enables a public bucket URL.\u003C\u002Fli>\n\u003Cli>Returning object bodies without checking for a missing key.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Continue with \u003Ca href=\"\u002Fcloudflare-config\">the configuration guide\u003C\u002Fa> or \u003Ca href=\"\u002Fcloudflare-config\u002Fd1\">D1\u003C\u002Fa> if metadata belongs in a database while objects live in R2.\u003C\u002Fp>\n",[33,36,39,42,45],{"id":34,"text":35},"quick-configuration","Quick configuration",{"id":37,"text":38},"create-the-bucket","Create the bucket",{"id":40,"text":41},"read-an-object-in-a-worker","Read an object in a Worker",{"id":43,"text":44},"from-wrangler-configuration","From Wrangler configuration",{"id":46,"text":47},"common-mistakes","Common mistakes",1790729614466]