Generate YouTube thumbnails with Workers·续

let text = urlencoding::decode(&text).map_err(|_| worker::Error::BadEncoding)?;

let text_png: TextPng = renderer.render_text_to_png_data(text.replace("+", " "), 60, "003682").unwrap();

let mut headers = Headers::new(); headers.set("content-type", "image/png")?;

Ok(Response::from_bytes(text_png.data)?.with_headers(headers)) }


After you have finished updating your project, start a local server for developing your Worker by running:

```sh
npx wrangler dev

This should spin up a localhost instance with the image displayed:

Run wrangler dev to start a local server for your Worker

Adding a query parameter with custom text, you should receive:

Follow the instructions above to receive an output image

To deploy your Worker, open your Wrangler file and update the name key with your project's name. Below is an example with this tutorial's project name:

{
    "$schema": "./node_modules/wrangler/config-schema.json",
    "name": "worker-to-text"
}
"$schema" = "./node_modules/wrangler/config-schema.json"
name = "worker-to-text"

Then run the npx wrangler deploy command to deploy your Worker.

npx wrangler deploy

A .workers.dev domain will be generated for your Worker after running wrangler deploy. You will use this domain in the main thumbnail image.

Create a Worker to display the original image

Create a Worker to serve the image you uploaded to Images by running:

npmyarnpnpm

npm create cloudflare@latest -- thumbnail-image
yarn create cloudflare thumbnail-image
pnpm create cloudflare@latest thumbnail-image

For setup, select the following options:

  • For What would you like to start with?, choose Hello World example.
  • For Which template would you like to use?, choose Worker only.
  • For Which language do you want to use?, choose JavaScript.
  • For Do you want to use git for version control?, choose Yes.
  • For Do you want to add an AGENTS.md file to help AI coding tools understand Cloudflare APIs?, choose Yes.
  • For Do you want to deploy your application?, choose No (we will be making some changes before deploying).

To start developing your Worker, cd into your new project directory:

cd thumbnail-image

This will create a new Worker project named thumbnail-image. In the src/index.js file, add the following code block:

export default {
    async fetch(request, env) {
        const url = new URL(request.url);
        if (url.pathname === "/original-image") {
            const image = await fetch(
                `https://imagedelivery.net/${env.CLOUDFLARE_ACCOUNT_HASH}/${IMAGE_ID}/public`,
            );
            return image;
        }
        return new Response("Image Resizing with a Worker");
    },
};

Update env.CLOUDFLARE_ACCOUNT_HASH with your Cloudflare account ID. Update env.IMAGE_ID with your image ID.

Run your Worker and go to the /original-image route to review your image.

Add custom text on your image

You will now use Cloudflare image transformations, with the fetch method, to add your dynamic text image as an overlay on top of your background image. Start by displaying the resulting image on a different route. Call the new route /thumbnail.

export default {
    async fetch(request, env) {
        const url = new URL(request.url);
        if (url.pathname === "/original-image") {
            const image = await fetch(
                `https://imagedelivery.net/${env.CLOUDFLARE_ACCOUNT_HASH}/${IMAGE_ID}/public`,
            );
            return image;
        }

if (url.pathname === "/thumbnail") {
        }

return new Response("Image Resizing with a Worker");
    },
};

Next, use the fetch method to apply the image transformation changes on top of the background image. The overlay options are nested in options.cf.image.

export default {
    async fetch(request, env) {
        const url = new URL(request.url);

if (url.pathname === "/original-image") {
            const image = await fetch(
                `https://imagedelivery.net/${env.CLOUDFLARE_ACCOUNT_HASH}/${IMAGE_ID}/public`,
            );
            return image;
        }

if (url.pathname === "/thumbnail") {
            fetch(imageURL, {
                cf: {
                    image: {},
                },
            });
        }

return new Response("Image Resizing with a Worker");
    },
};

The imageURL is the URL of the image you want to use as a background image. In the cf.image object, specify the options you want to apply to the background image.

Note

At time of publication, Cloudflare image transformations do not allow resizing images in a Worker that is stored in Cloudflare Images. Instead of using the image you served on the /original-image route, you will use the same image from a different source.

Add your background image to an assets directory on GitHub and push your changes to GitHub. Copy the URL of the image upload by performing a left click on the image and selecting the Copy Remote File Url option.

Replace the imageURL value with the copied remote URL.

if (url.pathname === "/thumbnail") {
    const imageURL =
        "https://github.com/lauragift21/social-image-demo/blob/1ed9044463b891561b7438ecdecbdd9da48cdb03/assets/cover.png?raw=true";
    fetch(imageURL, {
        cf: {
            image: {},
        },
    });
}

Next, add overlay options in the image object. Resize the image to the preferred width and height for YouTube thumbnails and use the draw option to add overlay text using the deployed URL of your text-to-image Worker.

fetch(imageURL, {
    cf: {
        image: {
            width: 1280,
            height: 720,
            draw: [
                {
                    url: "https://text-to-image.examples.workers.dev",
                    left: 40,
                },
            ],
        },
    },
});

Image transformations can only be tested when you deploy your Worker.

To deploy your Worker, open your Wrangler file and update the name key with your project's name. Below is an example with this tutorial's project name:

{
    "$schema": "./node_modules/wrangler/config-schema.json",
    "name": "thumbnail-image"
}
"$schema" = "./node_modules/wrangler/config-schema.json"
name = "thumbnail-image"

Deploy your Worker by running:

npx wrangler deploy

The command deploys your Worker to custom workers.dev subdomain. Go to your .workers.dev subdomain and go to the /thumbnail route.

You should see the resized image with the text Hello Workers!.

Follow the steps above to generate your resized image.

You will now make text applied dynamic. Making your text dynamic will allow you change the text and have it update on the image automatically.

To add dynamic text, append any text attached to the /thumbnail URL using query parameters and pass it down to the text-to-image Worker URL as a parameter.

for (const title of url.searchParams.values()) {
    try {
        const editedImage = await fetch(imageURL, {
            cf: {
                image: {
                    width: 1280,
                    height: 720,
                    draw: [
                        {
                            url: `https://text-to-image.examples.workers.dev/?${title}`,
                            left: 50,
                        },
                    ],
                },
            },
        });
        return editedImage;
    } catch (error) {
        console.log(error);
    }
}

By completing this tutorial, you have successfully made a custom YouTube thumbnail generator.

In this tutorial, you learned how to use Cloudflare Workers and Cloudflare image transformations to generate custom YouTube thumbnails. To learn more about Cloudflare Workers and image transformations, refer to Resize an image with a Worker.

Was this helpful?

YesNo

On this page

Generate YouTube thumbnails with Workers·续 - 图4Docs

{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/workers/tutorials/generate-youtube-thumbnails-with-workers-and-images/#page","headline":"Generate YouTube thumbnails with Workers and Cloudflare Image Resizing","description":"This tutorial explains how to programmatically generate a custom YouTube thumbnail using Cloudflare Workers. You may want to customize the thumbnail's design, call-to-actions and images used to encourage more viewers to watch your video.","url":"https://developers.cloudflare.com/workers/tutorials/generate-youtube-thumbnails-with-workers-and-images/","inLanguage":"en","image":"https://developers.cloudflare.com/workers/tutorials/generate-youtube-thumbnails-with-workers-and-images/og.png?v=de5ab2985a819cd9","dateModified":"2026-10-12","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/"},"keywords":["JavaScript","Rust"]}


description: This tutorial shows you how to build an SMS notification system on Workers to receive updates on a GitHub repository. Your Worker will send you a text update using Twilio when there is new activity on your repository. title: GitHub SMS notifications using Twilio image: https://developers.cloudflare.com/workers/tutorials/github-sms-notifications-using-twilio/og.png?v=70ce9cfc770cd366


Skip to content

Documentation Index
Fetch the complete documentation index at: https://developers.cloudflare.com/workers/llms.txt
Use this file to discover all available pages before exploring further.