Knowledge · GitHub

Cleaning Up Cloudflare Previews Automatically with GitHub Actions

From API token creation to GitHub Secrets, safe deletion rules, and troubleshooting

How to connect GitHub Actions to Cloudflare Workers Builds and Preview APIs, verify the successful production deployment, and delete only the intended Preview.

Connecting GitHub and Cloudflare Workers makes it possible to review website changes on a Preview deployment from a working branch.

However, merging work into main does not guarantee that the old Preview disappears. A previous deployment can remain available at a separate address.

This article documents how I explored cleaning up only the matching Preview after the corresponding production deployment has succeeded, using GitHub Actions and Cloudflare APIs.

1. How the cleanup workflow is supposed to work

The intended sequence is:

  1. A GitHub Pull Request is merged into main.
  2. GitHub Actions begins the cleanup workflow.
  3. The workflow checks whether Cloudflare successfully completed a Production Build for the merged commit.
  4. It identifies the Preview matching the PR branch and commit.
  5. It deletes only the identified Workers Preview.

If production deployment failed or the Preview cannot be identified conclusively, the workflow should delete nothing. Older Previews created before this automation may require separate investigation.

2. Create a Cloudflare API token

GitHub Actions needs an API token to call Cloudflare.

Open the Cloudflare API Tokens page, choose Create Token → Create Custom Token, and provide a descriptive name such as Preview-Cleanup-Automation.

Permissions to examine

For a workflow that queries Workers Builds and deletes a Workers Preview, consider these permission scopes:

ScopePermissionAccess
AccountWorkers Builds ConfigurationEdit
AccountWorkers ScriptsEdit

The Workers Builds API requires a user-scoped API token. Verify the actual permission names and requirements against Cloudflare's current documentation and the specific API calls you plan to make. Grant no more access than needed.

Additional token settings

  • Account Resources: Prefer the one account used by this automation rather than All accounts.
  • Client IP Address Filtering: GitHub-hosted runners can change IP addresses. Leave this filter unset if you do not use a predictable source IP.
  • TTL: Choose expiration according to your security policy. If you set an expiration date, remember to refresh the GitHub Secret before then.

Proceed through Continue to summary → Create Token and store the token securely. Its plaintext may not be displayed again after creation.

Distinguish a token used by Cloudflare's own build/deployment service from a token GitHub Actions uses to call the Cloudflare API.

3. Find the Cloudflare Account ID

In the Cloudflare dashboard, open Workers & Pages for the intended account and locate the Account ID under account details. Cloudflare also maintains instructions for finding account and zone IDs.

An Account ID is not your sign-in email address or a Zone ID.

ValueMeaning
Account IDIdentifier for the Cloudflare account
Zone IDIdentifier for a particular domain zone
EmailAddress used to sign in to Cloudflare
API TokenSecret authentication string for API calls

Verify that the identifier belongs to the account hosting the relevant Worker.

4. Register GitHub Actions Secrets

Open the relevant repository on GitHub and navigate to:

Settings → Secrets and variables → Actions → New repository secret

You can also use a URL in this form:

https://github.com/OWNER/REPOSITORY/settings/secrets/actions

Replace OWNER and REPOSITORY with the actual owner and repository name.

Secret nameValue to enter
CLOUDFLARE_API_TOKENThe API token issued by Cloudflare
CLOUDFLARE_ACCOUNT_IDThe Cloudflare Account ID

The names on the left are the names that the workflow references. The values on the right must be taken from your own account. Never paste secrets into source code or a published blog article.

Existing GitHub Secret values cannot be read back through the interface. If a value is incorrect, update it.

5. Connect safe cleanup to GitHub Actions

Place a workflow YAML file under .github/workflows/ in the repository.

It should enforce the following conditions:

  1. Handle the pull_request closed event.
  2. Confirm the PR was actually merged into main.
  3. Exclude pull requests from external forks.
  4. Verify that the Production Build succeeded for the corresponding merge commit SHA.
  5. Compare PR branch, commit, and Preview URL using Cloudflare Builds API metadata.
  6. Delete only the matching Workers Preview.

You can use supported Wrangler Preview-deletion functionality if appropriate. Do not guess a Preview identifier merely from a branch name, and do not treat every deployment-specific URL as a branch Preview.

Legacy Version Previews and Workers Previews need to be distinguished. If the evidence is insufficient to identify a deletion target, skip deletion.

This workflow can be triggered by a PR merge instead of running repeatedly on a timer.

6. The Account ID mistake I actually made

While setting this up, I accidentally entered my Cloudflare sign-in email address as CLOUDFLARE_ACCOUNT_ID.

GitHub Actions started, but Worker lookup failed with:

Cloudflare Worker lookup failed with HTTP 404 (Cloudflare errors: 7003)

That initially looked like it could be a token permission problem. In the actual incident, though, the confirmed mistake was entering an email address where an Account ID was expected.

If you see a similar error, check:

  1. Is this the correct Cloudflare Account ID?
  2. Did you accidentally enter an email address or a Zone ID?
  3. Does the API token apply to the intended account?
  4. Does the token have the permissions needed to inspect builds and delete the Preview?

After fixing the Secret, you can rerun the GitHub Actions workflow.

7. Verify that the Preview really disappeared

Open the repository's Actions tab and inspect the workflow run.

A workflow running does not by itself mean the Preview was deleted. Confirm:

  • Did the corresponding Production deployment finish successfully?
  • Was only this PR's Preview selected?
  • Did the deletion operation complete successfully?
  • Does the old Preview URL no longer serve the deleted Preview?

If the target cannot be identified, cleanup must be skipped. Neither the production Worker nor another branch's Preview should be affected.

Automation reduces repetitive tasks, but only when its authentication, permissions, target identification, and failure behavior have been verified.

Why I started thinking about cleanup

I did not begin by wanting to automate Preview deletion.

I started by finding it frustrating to exchange HTML files every time I wanted to review a blog draft. That led to a broader investigation of GitHub branches, Cloudflare Preview, and a simpler editorial workflow.

During that process I realized that a Preview might remain after a merge, and I started exploring GitHub Actions to clean it up.

I described how the initial inconvenience gradually led me to think about this automation in a separate Story.

Related readingFrom Exchanging HTML Files to Rethinking How I Publish My Blog

Starting with the inconvenience of reviewing HTML files, I considered private GitHub branches and Cloudflare Zero Trust before choosing separate editorial and visual review stages.

Official references

GitHubWebsite operationsGitHub ActionsCloudflare WorkersPreviewAPI TokenSecretsautomation
Connected projectsBLOG
Practical KnowledgeVerified follow-up guides will be linked when published.

Continue reading

Story · Development experience

From Exchanging HTML Files to Rethinking How I Publish My Blog

How reviewing drafts led me through GitHub branches, Cloudflare Preview, and a simpler editorial workflow

Starting with the inconvenience of reviewing HTML files, I considered private GitHub branches and Cloudflare Zero Trust before choosing separate editorial and visual review stages.

Published Oct 13, 2026
Read