Skip to content
HTML/CSS to ImageDocs

Generate images from a Cloudflare Worker using capa’s HTML/CSS to Image capability. Deploy the capability to your Cloudflare account, then call it from your application Worker through a service binding.

View capability on GitHub Get API credentials

For a direct SDK integration, we also maintain the official @html-css-to-image/client TypeScript SDK. See the TypeScript examples and SDK repository. capa is useful when you want a separate Worker to own the API credentials and expose API operations to other Workers through RPC.

You’ll need a Cloudflare account, Bun, and your HTML/CSS to Image API ID and API Key from the dashboard.

Clone capa and install its dependencies from the repository root:

Terminal window
git clone https://github.com/acoyfellow/capa.git
cd capa
bun install
cd capabilities/htmlcsstoimage

Set both credentials as Worker secrets. Wrangler prompts for each value, so you don’t need to put credentials in a command or configuration file:

Terminal window
bunx wrangler secret put HTMLCSSTOIMAGE_USER_ID
bunx wrangler secret put HTMLCSSTOIMAGE_API_KEY
bunx wrangler deploy

Use your API ID for HTMLCSSTOIMAGE_USER_ID and your API Key for HTMLCSSTOIMAGE_API_KEY. The capability uses these credentials for HTTP Basic authentication with the HTML/CSS to Image API.

The included configuration names this Worker capa-htmlcsstoimage, disables its workers.dev URL, and exports the HtmlcsstoimageCapability RPC entrypoint. Its HTTP handler returns 404; callers use a service binding instead of a public HTTP endpoint.

In your application’s wrangler.jsonc, add this entry to the services array:

{
"services": [
{
"binding": "HTMLCSSTOIMAGE",
"service": "capa-htmlcsstoimage",
"entrypoint": "HtmlcsstoimageCapability"
}
]
}

Keep your application’s existing name, main, and compatibility_date settings. If you renamed the capability Worker, update service to match. The binding name becomes env.HTMLCSSTOIMAGE in your application.

From your application directory, generate types with both Worker configurations. Adjust the second path to your local capa checkout:

Terminal window
bunx wrangler types -c ./wrangler.jsonc -c ../capa/capabilities/htmlcsstoimage/wrangler.jsonc

This generates worker-configuration.d.ts with the Env interface and the capability’s RPC binding type. See Cloudflare’s RPC service binding documentation and RPC TypeScript documentation for details.

Call image.create from your application Worker. capa returns an envelope containing result and evidence; check the verdict and result before using the image URL.

export default {
async fetch(request, env) {
if (request.method !== "POST") {
return new Response("Use POST to create an image", {
status: 405,
headers: { Allow: "POST" },
});
}
// Apply your application's authentication and rate limits here.
const { result, evidence } = await env.HTMLCSSTOIMAGE.image.create({
html: "<div class='card'>Hello from Cloudflare Workers!</div>",
css: ".card { padding: 40px; background: #03B875; color: white; font: 32px sans-serif; }",
});
if (evidence.verdict === "fail" || !result?.url) {
return Response.json({ error: "Image creation failed" }, { status: 502 });
}
return Response.json({ url: result.url });
},
} satisfies ExportedHandler<Env>;

This example assumes Env has been generated with the RPC binding type for the capability’s entrypoint. Deploy your application Worker after adding the binding. A successful request returns JSON containing the generated image URL. Standard API permissions, rate limits, and account usage apply; creating an image requires images:create.

The generated capability also includes operations for batches, templates, OG configurations, proxies, storage destinations, and usage. See the capability README for examples, including retrieving rendered image bytes.

How secrets and bindings protect your credentials

Section titled “How secrets and bindings protect your credentials”

Cloudflare Worker secrets are encrypted bindings available to the capability Worker at runtime. Once set, their values aren’t visible in Wrangler or the dashboard. They stay out of your source code and browser responses.

Your application Worker receives a service binding to call the capability, rather than a copy of the API credentials. The capability makes the authenticated request to HTML/CSS to Image over HTTPS. This keeps credential handling in one Worker while allowing your application to receive the resulting image URL.

The binding grants access to the capability’s operations, so protect any application endpoint that invokes it with your own authentication and rate limits. Use a dedicated API key with only the permissions your application needs. Worker code can read its own secrets: avoid logging credentials or returning them in responses, and review third-party code before deploying it.

For local development, place credentials in a gitignored .dev.vars file in the capability directory. Cloudflare documents local secret setup; don’t commit that file.