1 Introduction
Many friends who use Cloudflare CDN often encounter this problem: after modifying some content on the website, they find that the changes do not take effect immediately after refreshing the webpage. At this time, everyone's first reaction is often to go to the Cloudflare dashboard and click “Purge Everything”:

Although this can solve the problem immediately, it has a major side effect—all static resources (HTML, CSS, JS, images, etc.) will be purged, and visitors will have to reload all content from the origin server when accessing the website,which leads to slower page loads, wasted bandwidth, and even affects SEO.
In fact, most of the time, what we really want to purge is justHTML pages, for example, when functions.php, header.php, or footer.php is modified, causing changes in the page structure, but Cloudflare is still serving the old HTML cache. In this case,purging only HTML while leaving CSS, JS, and images untouchedis the most reasonable and precise approach.
Although the Cloudflare dashboard itself does not provide an intuitive option like ”Purge HTML Only”, the good news is that now, including free users, everyone can use the 4 methods provided by the dashboard to flexibly purge cache content (previously, free users could only use the URL method, while the other 3 methods were once exclusive to Pro and higher plans)。
Currently, Cloudflare supports 4 custom cache purging methods:

Among these methods:
- Purge by URL — too tedious, especially when you modify multiple pages, you need to list the full URLs one by one, which is error-prone and difficult to maintain.
- Purge by Hostname — too aggressive, directly purging all content under the entire subdomain, which is equivalent to a ”mild version” of purging all cache, and the control granularity is too coarse.
- Purge by Tag and Prefix — these two methods balance flexibility and control.If resources were consciously grouped reasonably using Tags or path prefixes during early development,then during later operations, you only need to specify a tag or path prefix to precisely purge the relevant cache, avoiding full-site invalidation at every turn.
Therefore, from the perspective oflong-term operations and automated deployment,it is recommended to introduce Cache-Tag or path prefix design right from the start of website construction. This way, whether operating through the dashboard or API in the future, you can elegantly purge cache content instead of ”indiscriminate bombing”.
2 Based on Cache-Tag Method
1 Introduction to Cache-Tags
Cache-Tag is an advanced cache management feature provided by Cloudflare. It allows users to add custom tags to cached content for more precise control over cache purging. Cache-Tags are set by the origin server (such as WordPress) in HTTP response headers. When Cloudflare fetches and caches this content in the CDN, it reads and associates these tags.
By using Cache-Tags, you can assign different tags to different types of resources (such as HTML pages, CSS files, JS files, images, etc.). This way, when needed, you can precisely purge the cache of these specific resources via tags, rather than purging the entire site's cache.
Note: Cache-Tags are for Cloudflare's caching system and have nothing to do with browser caching behavior.
2 Adding Cache-Tags at the Origin Server
Depending on different origin server deployment methods and environments, different methods can be used to add Cache-TagsBelow are several common deployment methods and corresponding operation methods:
WordPress Deployment
For WordPress users, you can add Cache-Tag to responses through plugins or custom code. A common practice is to use PHP functions to set custom Cache-Tags in the functions.php file, or use caching plugins that specifically support Cache-Tag.
- Custom Code: Add Cache-Tag to HTTP response headers by using the header() function in functions.php. For example, you can dynamically generate different tags for specific pages, posts, or categories.
- plugins: Some caching plugins (such as W3 Total Cache、WP Super Cache etc.) provide options to work with Cloudflare, allowing you to add custom tags to cached content.
Taking custom code as an example, you only need to add the following code to functions.php to set the cache tag ”html-tag” for all HTML content (it is still highly recommended to use code snippets to centrally manage all code that needs to be inserted into theme files):
function add_cache_tags_to_headers() {
// 仅在前端页面执行,避免后台管理页面
if (is_admin()) {
return;
}
// 仅对 HTML 页面设置 Cache-Tag
if (is_page() || is_single() || is_home() || is_archive()) {
header('Cache-Tag: html-tag');
}
}
add_action('send_headers', 'add_cache_tags_to_headers');
Explanation of Key Points:
- Frontend Page Limitation: Use is_admin() to ensure that the cache tag is only executed on frontend pages, avoiding unnecessary addition of Cache-Tag to backend admin pages.
- Only for HTML Pages: Determine the current page type using is_page(), is_single(), is_home(), and is_archive(), and only add Cache-Tag under these page types to avoid applying it to resources like CSS and JS.
- Directly Set HTTP Headers: Omits array processing logic and directly uses header(‘Cache-Tag: html-tag’) to reduce extra computation and improve code execution efficiency.
- Streamlined Logic, Improved Readability: Removes matching logic for resources like CSS, JS, and images, making the code clearer, easier to understand, and convenient to maintain and adjust.
How to verify success? When accessing the origin site directly after setting it up, you can see it in the response headers of the HTML page under the ”Network” - “Headers” tab of the browser developer tools (only visible when accessing the origin site directly):

The Cache-Tag for HTML works because WordPress processes page requests through PHP and adds the corresponding tag in the send_headers Hook. Static resources like CSS, JS, and images are served directly by Nginx or Apache and do not go through WordPress's PHP processing logic, so send_headers cannot affect these files.
To implement Cache-Tag settings for CSS and JS, you need to configure them in Apache or Nginx paired with WordPress. Taking Apache as an example (since WordPress deployed via Docker is based on Apache), you need to add the following settings inhtml/.htaccess:
# Ensure Apache version compatibility to prevent unexpected crashes""<FilesMatch "\.css
Then restart Docker, and you can set the corresponding Cache-Tag for CSS, JS, and images (limited to images on the origin site under the same domain, such as images in the WordPress Media Library).
Using Nginx as a Reverse Proxy
If the origin site uses Nginx as a reverse proxy server, you usually need to set Cache-Tag in the Nginx configuration file. By using conditions such as the requested URL path, request headers, and query parameters, Nginx can dynamically add Cache-Tag to different resources.
- Based on URL Path: Decide which tags to use based on the requested URL path. For example, add Cache-Tag: product to all page resources under the /products/ path.
Nginx Configuration Example:
For example, if you want to add Cache-Tag: product to all page resources under the /products/ path:
location /products/ {
add_header Cache-Tag "product";
}
Explanation: When the requested URL path starts with /products/, Nginx will add Cache-Tag: product to the response. This method is very suitable for path-based resource grouping (such as product pages, category pages, etc.).
- Based on Request Headers or Query Parameters: You can dynamically add different Cache-Tags to different requests based on HTTP request headers (e.g., User-Agent) or query parameters (e.g., ?category=xyz).
Nginx Configuration Example:
If you want to add different Cache-Tags based on the user's User-Agent request header:
location / {http_user_agent ~* "mobile") {http_user_agent !~* "mobile") {
Explanation: Based on the value of the User-Agent request header, if the user is accessing using a mobile device, Nginx will add Cache-Tag: mobile-tag to the response; if accessing from a desktop device, it will add Cache-Tag: desktop-tag.
- Adding Cache-Tag Based on Query Parameters
For example, if the URL contains the query parameter ?category=xyz, and you want to add Cache-Tag: category-xyz to all such requests:
location / {
if ($arg_category = "xyz") {
add_header Cache-Tag "category-xyz";
}
}
Explanation: When the requested URL contains the query parameter category=xyz, Nginx will add Cache-Tag: category-xyz to the response. This method is particularly suitable for adding tags to different content based on different filtering conditions (such as product categories, article classifications, etc.).
Using Apache as a Web Server
If the origin site uses Apache as a Web server, you can usually add Cache-Tag through the .htaccess file. Apache provides powerful conditional judgment features, allowing you to dynamically add custom tags to responses based on request paths, query parameters, or request headers. This makes fine-grained control of caching in different situations more flexible.
.htaccess Configuration Example:
- Adding Cache-Tag Based on URL Path
For example, if you want to add Cache-Tag: product to all pages under the /products/ path:
<IfModule mod_headers.c>
<Location "/products/">
Header set Cache-Tag "product"
</Location>
</IfModule>
Explanation: When the requested URL path starts with /products/, Apache will add Cache-Tag: product to the response of all resources under that path. This method is suitable for grouping resources based on path structure, such as adding a unified tag to all product pages.
- Adding Cache-Tag based on request headers
If you want to determine the Cache-Tag based on request headers (such as User-Agent), you can use the following configuration:
<IfModule mod_headers.c>
SetEnvIf User-Agent "mobile" CACHE_TAG=mobile-tag
SetEnvIf User-Agent "desktop" CACHE_TAG=desktop-tag
Header set Cache-Tag %{CACHE_TAG}e env=CACHE_TAG
</IfModule>
Explanation: Based on the value of the User-Agent request header, Apache will check whether the access is from a mobile device or a desktop device. If it is a mobile device, it adds Cache-Tag: mobile-tag; if it is a desktop device, it adds Cache-Tag: desktop-tag. This method is suitable for setting different cache tags based on the accessing device.
- Adding Cache-Tag Based on Query Parameters
If you want to add a Cache-Tag to the request based on query parameters in the URL (for example, ?category=xyz), you can use the following configuration:
<IfModule mod_headers.c>
RewriteEngine On
RewriteCond %{QUERY_STRING} category=xyz
RewriteRule .* - [E=CACHE_TAG:category-xyz]
Header set Cache-Tag %{CACHE_TAG}e env=CACHE_TAG
</IfModule>
Explanation: When the URL query parameter category=xyz exists, Apache will add Cache-Tag: category-xyz to the response of that request. This method is suitable for distinguishing cache tags based on specific query parameters (such as product categories, article categories, etc.).
Using other CDNs or reverse proxy services
If your site does not use Cloudflare, but instead uses other CDNs or reverse proxy services (such as Fastly, AWS CloudFront, etc.), you can add Cache-Tag or similar tags according to the documentation of those services. Most modern CDNs support some form of cache tagging mechanism, although the specific implementation may vary.
3 CDN Content Purging Based on Cache-Tags
If you want to purge the category content corresponding to a certain cache tag in the CDN, the operation is very simple. You only need to go to the ”Caching” - “Configuration” - “Custom Purge” section of the dashboard:

Select ”Tag”, and then enter the tag of the corresponding category to purge it:

3 Based on Path Prefix Method
If you want to purge the content under a certain path in the CDN, the operation is very simple. You don't need to spend a long time configuring the origin server to apply tags like you do with the cache tag method. Instead, you only need to go to the ”Caching” - “Configuration” - “Custom Purge” section of the dashboard:

Select ”Prefix”, and then enter the corresponding prefix to purge it:

If the website's early design phase consciously considered the issue of subsequent cache purging, then systematically planning the URL path structure is equivalent to implementing a ”categorization by directory” mechanism in advance. The biggest benefit of doing this is: even if you do not use the Cache-Tag feature, you can still leverage the Cloudflare API's prefix matching purge featureto efficiently achieve logically grouped cache purging.
For example, if you place all blog posts under the /posts/ directory and all product pages under /products/, then when you publish or update an article, you only need to purge the cache under the /posts/ prefix via the API to clean up the HTML, cover images, related scripts, etc., of the relevant articles all at once, without having to list the URLs one by one.
In contrast, if the URL path design is messy and irregular, you will have to specify specific URLs one by one later, which is both easy to miss and increases maintenance costs.
This “structured path = implicit Cache-Tag” design approach is suitable for:
- Static blogs / documentation websites: URL structures are usually very regular;
- E-commerce websites: Prefix paths can be designed by category, brand, campaign, etc.;
- Multi-language websites: Language can be used as a path prefix, such as /en/, /zh/, /fr/, etc.;
- Large portal websites: Different modules can be divided into paths by functional modules, such as /news/, /events/, /videos/, etc.
In other words, if you do not have the conditions to use Cache-Tag and are unwilling to modify the server-side logic, then a ”well-planned URL prefix” is one of the most reliable assets for your cache purging operations. Rather than calling it a makeshift solution, it is itself an architectural foresight.
4 Using API to Purge Specific Cache Content in CDN
1 Overview
Some people may not like frequently opening the Cloudflare dashboard for manual operations, especially in daily maintenance or automated deployment workflows, where this approach seems neither efficient nor realistic. In certain automated scenarios, such as when a website publishes a new article, updates page templates, or runs CI/CD deployment scripts, we also cannot rely on a graphical interface to purge the cache. At this time, the API provided by Cloudflare becomes particularly important.
By calling Cloudflare's cache purge API, we can programmatically manage the cache, precisely purging the cache under specific URLs, paths, tags (Cache-Tag), or hostnames without logging into the dashboard. This method is not only flexible but also very suitable for integration into automated workflows, such as:
- Automatically purging the cache of the corresponding page after publishing an article in WordPress;
- Purging only old resources under specific paths after deploying static resources;
- Regularly purging cache content under certain tags to ensure that updates to front-end pages are reflected to visitors in a timely manner.
Compared to the brute-force approach of ”purging all cache”, the fine-grained control capability of the API can effectively avoid unnecessary cache invalidation, thereby improving website performance and user experience.
2 Purging Cache Content of Specific Cache-Tag Categories via API
4.2.1 Prerequisites
To use the API, you need the following information:
- API Token(Recommended): With Zone.Cache Purge permission.
- Zone ID: The unique identifier of your domain in Cloudflare.
- Account Email(if using API Key).
- API Endpoint: The address used for cache purging.
4.2.2 API Request Structure (Purge Cache-Tag)
Request Address:
POST https://api.cloudflare.com/client/v4/zones/{zone_id}/purge_cache
Request Headers(using API Token):
Authorization: Bearer YOUR_API_TOKEN
Content-Type: application/json
Request Body(Purge by tag):
{
"tags": ["html-tag"]
}
4.2.3 curl call example
curl -X POST "https://api.cloudflare.com/client/v4/zones/YOUR_ZONE_ID/purge_cache" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
--data '{"tags": ["html-tag"]}'
You can add this command to your website deployment scripts, WordPress hooks (such as publish_post), or CI/CD pipelines to automatically purge the cache when specific events are triggered.
Note 1:Multiple tags can be purged at the same time, simply by writing them in an array format, for example: ["html-tag", "homepage", "footer"]。
Note 2:API Token Permission Recommendation: For security, it is recommended to create a dedicated API Token and grant it only Cache Purge permissions, avoiding the use of the Global API Key.
Note 3: If you are using an API Key instead of a Token, please use the following headers instead:
X-Auth-Email: [email protected]
X-Auth-Key: your-global-api-key
3 Purging Cache Content under Specific Paths via API
4.3.1 Prerequisites
To use the API to purge cached content under a specific path, you need the following information:
- API Token(Recommended): With Zone.Cache Purge permission.
- Zone ID: The unique identifier of your domain in Cloudflare.
- Account Email(if using API Key).
- API Endpoint: The address used for cache purging.
4.3.2 API Request Structure (Purge cache under specific paths)
Request Address:
POST https://api.cloudflare.com/client/v4/zones/{zone_id}/purge_cache
Request Headers(using API Token):
Authorization: Bearer YOUR_API_TOKEN
Content-Type: application/json
Request Body(Purge by path prefix):
{
"prefixes": ["https://example.com/blog/"]
}
In the request body, the prefixes array contains the path prefixes for which the cache needs to be purged. Cloudflare will purge all matching cached resources based on these path prefixes.
4.3.3 curl call example
curl -X POST "https://api.cloudflare.com/client/v4/zones/YOUR_ZONE_ID/purge_cache" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
--data '{"prefixes": ["https://example.com/blog/", "https://example.com/products/"]}'
You can add this command to your website deployment scripts, WordPress hooks (such as publish_post), or CI/CD pipelines to automatically purge the cache when specific events are triggered.
Note 1:Path Prefix Purge: By specifying a path prefix (such as /blog/ or /products/), you can purge all cached resources matching that path. This is much cleaner than listing URLs one by one, especially when you know that all resources under a certain path need to be purged.
Note 2:Multiple Path Purge: Multiple path prefixes can be purged at the same time, simply by writing them in an array format, for example:["https://example.com/blog/", "https://example.com/products/"]。
Note 3:API Token Permission Recommendation: For security, it is recommended to create a dedicated API Token and grant it only Cache Purge permissions, avoiding the use of the Global API Key.
Note 4:If you are using an API Key: instead of an API Token, please use the following headers for authentication:
X-Auth-Email: [email protected]
X-Auth-Key: your-global-api-key
5 How to Verify If Cache-Tag Is Taking Effect?

As shown in the official Cloudflare documentation on Cache-Tag above, before receiving a response with Cache-Tag from the origin server and returning it to website visitors, Cloudflare will directly delete all Cache-Tags (which is understandable, as Cache-Tags are meant for the CDN provider and have nothing to do with visitors). Therefore, Cache-Tags cannot be seen in the developer tools of the visitor's browser (which is why I emphasized in previous articles that they can only be seen by directly accessing the origin server).
But in this case, how do we verify if Cache-Tag is actually working? It's actually very simple. Taking my test site, which does not use APO but uses regular Page Rules for caching, as an example, first set the rules as follows:

Use this Page Rule to enable caching for the test site, set to ”Cache Everything + Edge Cache TTL of 2 hours”. With this configuration, Cloudflare's edge nodes will cache the homepage content for 2 hours, but since no browser TTL is set, the browser will not cache the page content locally.
The purpose of doing this is for the subsequent test: I will use the ”Normal Reload” (not hard refresh) function to visit the homepage again. If the browser also caches the homepage locally, then even if Cloudflare's edge cache has expired, the browser might still read the page content directly from the local cache, interfering with the judgment. The current setting ensures that every load must fetch resources from Cloudflare, thereby more accurately observing and testing the CDN cache status (such as determining whether cf-cache-status is HIT or MISS).
Under normal circumstances, the CF-Cache-Status result seen when visiting the homepage is ”HIT”:

At this point, as described earlier in the article, first purge directly in the ”Tag” section of Custom Purge in the dashboard cachehtml-tagtag:

Then reload (refresh) the page normally. At this point, if the html-tag purge was successful, this page should not be in the cache, so the CF-Cache-Status result should be ”MISS”:

6 Summary
For average personal webmasters, using Cache-Tag makes O&M work much more efficient, and they no longer have to tearfully ”Purge Everything”. Even for webmasters who use the APO feature, Cache-Tag can often work wonders. Why is that?
Generally speaking,using APO actually does not require frequent manual cache purging, because APO itself is designed to solve WordPress cache refresh issues: it listens in the background for typical WordPress update operations, such as publishing new posts, updating pages, modifying menus, etc. After these events occur,APO will automatically trigger a cache refresh for the corresponding pagesThat is to say, in most cases,you only need to wait a few minutes to a few hours(Cloudflare officially says ”within minutes”) for the new content to automatically take effect, without manual intervention.
However,this ”automatic refresh” is not real-time, nor can it cover all scenariosFor example, if you modify functions.php, theme template files, or adjust the header/footer structure, even if these changes directly affect the final output content of the page,APO will not detect these changes, let alone automatically refresh the cacheThis is because APO's cache refresh mechanism essentially relies on WordPress's hook system to perceive content changes—such as updating posts, publishing pages, switching themes, saving menus, etc. These are changes at the WordPress content level, and Cloudflare can automatically purge the corresponding cache via API notifications. However, modifications to template files, plugin files, and PHP logic codewill not trigger the relevant WordPress event hooks, so Cloudflare naturally ”cannot see” these changes, and the cached content may remain in its old state.
In other words, under these ”structural modification” scenarios,APO is not ”refreshing automatically a bit slowly”, but rather ”not refreshing at all”, even if you wait for a longer time, it will not take effect, unless you manually purge cache, or make a content-level modification through the backend, such as randomly editing and saving an article, which can also trigger APO to refresh the relevant pages (actually, this method is the simplest, it's just very low-tech and I disdain to use it; additionally, this can only target modifications in terms of template and structural adjustments, such as modifying functions.php).
Therefore, for thosesites that need to frequently adjust templates, optimize structures, or debug output logic,relying on APO alone is not enough, and you still need to rely on the ”manual purge” function to ensure that the latest content is presented on the frontend instantly. And if you also want this ”manual purge” to be as smart and selective as possible (for example, only purging HTML, or only purging certain types of pages), then Cache-Tag is an excellent tool. Of course, planning prefixes in advance and combining them with the custom purge cache function for specified prefixes is also similar.