- Docs
- Guides
- Advanced
- Storage destinations
- Upload to Cloudflare R2
Upload to Cloudflare R2
Send every rendered image or PDF to a Cloudflare R2 bucket you control.
HTML/CSS to Image connects to Cloudflare R2 through its S3-compatible API. You provide an R2 access key, secret, Cloudflare account ID, and the bucket’s data jurisdiction.
Before you begin
Section titled “Before you begin”You need:
- An existing R2 bucket.
- The Cloudflare account ID that owns it.
- The bucket’s data jurisdiction, if it was created with one.
- An optional key prefix, such as
hcti-renders.
Create R2 S3 credentials
Section titled “Create R2 S3 credentials”In the Cloudflare dashboard, open R2 Object Storage, select Manage API Tokens, and create an account or user API token.
- Choose Object Read & Write permission.
- Scope the token to the destination bucket when possible.
- Create the token.
- Copy the Access Key ID and Secret Access Key. Cloudflare shows the secret only once.
Read and write access lets HCTI upload renders and reload an original for a later resize, crop, or format conversion when Disable HCTI Storage is selected. HCTI uses delete access only to clean up connection-test objects; it does not delete rendered images from R2.
Add Cloudflare R2 to HCTI
Section titled “Add Cloudflare R2 to HCTI”Open the Storage Destinations dashboard, click Add storage destination, and enter:
| HCTI field | Cloudflare value |
|---|---|
| Provider | Cloudflare R2 |
| Bucket | Existing R2 bucket name |
| Key prefix | Optional folder-like prefix, without leading or trailing slashes |
| Account ID | Cloudflare account ID |
| Access key ID | R2 token’s Access Key ID |
| Secret access key | R2 token’s Secret Access Key |
| Data jurisdiction | The jurisdiction used when the bucket was created |
Choose the R2 data jurisdiction
Section titled “Choose the R2 data jurisdiction”The setting determines which R2 endpoint HCTI uses:
| Dashboard option | Endpoint | Use when |
|---|---|---|
| Default | <account-id>.r2.cloudflarestorage.com |
The bucket has no jurisdiction restriction. This is also the correct option for a bucket with only a location hint. |
| European Union | <account-id>.eu.r2.cloudflarestorage.com |
The bucket was created in the European Union jurisdiction. |
| FedRAMP | <account-id>.fedramp.r2.cloudflarestorage.com |
The bucket was created in the FedRAMP jurisdiction. |
The wrong jurisdiction points HCTI at an endpoint that cannot access the bucket. If you change this setting later, run Test connection again before saving.
Test and save the destination
Section titled “Test and save the destination”- Click Test connection.
- Enable and save the destination after the test succeeds.
- Copy the destination
id.
The test writes a small object under <key-prefix>/.hcti/connection-tests/. Cleanup is best-effort and does not determine whether the connection passes.
Upload an HCTI image to R2
Section titled “Upload an HCTI image to R2”Pass the destination ID as storage_destination_id when you create an image:
curl -X POST https://hcti.io/v1/image \ -u 'user-id:api-key' \ -H 'Content-Type: application/json' \ -d '{ "url": "https://example.com", "storage_destination_id": "your-storage-destination-id" }'Rendering is lazy. With normal HCTI storage enabled, request the returned image URL to render the image and write both copies. With Disable HCTI Storage selected, send an authenticated PUT request to the returned /v1/store/... URL.
The base object is stored as <key-prefix>/<image-id>.png, or .pdf when the request uses pdf_options. R2 bucket access remains under your control; HCTI does not make the object public.
Troubleshooting Cloudflare R2 uploads
Section titled “Troubleshooting Cloudflare R2 uploads”- The connection test cannot find the bucket — Confirm the bucket name, account ID, and data jurisdiction.
- Authentication fails — Use the S3 Access Key ID and Secret Access Key generated for R2, not a general Cloudflare API token string.
- The secret is unavailable — Create a new R2 API token; Cloudflare does not show the secret again after creation.
- A later transformation fails with HCTI Storage disabled — Confirm the token has object read access as well as write access.
- The connection worked before the jurisdiction changed — Test again; changing the jurisdiction changes the R2 endpoint.
Cloudflare documents creating R2 S3 API credentials and jurisdiction-specific R2 endpoints.
Automate destination setup
Section titled “Automate destination setup”You can also automate configuration through the Storage destinations API or MCP tools.
Need help?
Talk to a human. Email support@htmlcsstoimage.com and we’ll help you get started.