Contents
- 1 Introduction
- 2 Setup steps
- 2.1 Adding endpoints
- 2.2 Failure Settings
- 2.3 Verification
- 2.4 Other security configurations
- 3 Extended knowledge: F5 Distributed Cloud Robot Defense
- 4 Conclusion
1 Introduction
Under the "Security" tab of the Cloudflare dashboard, there is an "API Shield" feature:

This feature is obviously used to protect APIs, but I have never built my own APIs that need to be protected, so I have no chance to use it.FreeStudy this feature.
However, as I have written two articles recently involving self-built APIs (seeHome Data Center Series: Building an Efficient and Secure Random Image API: Cloudflare Worker + R2 + KV Practical GuideandHome Data Center Series Cloudflare Worker + KV: Building WordPress Cloud Article Reading Statistics), and suddenly I realized that I already have the materials to research this function. This week’s research target will be “API Shield”.
Note: Cloudflare has recently launched a new dashboard with a lot of changes in the functional layout. For example, the "API Shield" function is called "Web Assets" in the new dashboard:

However, in order to be compatible with the previous Cloudflare-related articles I wrote, I still use the old dashboard to take screenshots.
2 Setup steps
2.1 Adding endpoints
2.1.1 What is an endpoint and the purpose of creating an endpoint
In Cloudflare's API protection, "endpoint" refers to the specific access entry and access method of an API. For example, when I built cloud-based article reading statistics, I used "/views-track" as the API entry to record the number of article readings and query the number of readings.
The core of the endpoint is to clarify the normal access scope of the API, including the allowed request path, request method (such as GET, POST, etc.), source (such as a specific IP or domain name), and expected access mode. By defining these rules, Cloudflare can identify which are normal requests that conform to business logic and which may be abnormal or malicious traffic, thereby establishing a clear access boundary and laying the foundation for subsequent traffic monitoring, abuse detection and protection strategies. For example, if an endpoint should only accept POST requests, but a large number of GET requests appear, this may be potential abuse.
2.1.2 Three ways to add endpoints
In the "Endpoint Management" - "Add Endpoint" section, you can add endpoints:

Cloudflare provides three ways to add endpoints: manually add, upload the schema, and select from Discover:

- "Manual Add" is suitable for situations where you need to accurately define the API endpoint. Users can enter information such as the path, request method (excluding request details) by themselves;
- "Upload Architecture" supports importing standardized API specification files such as OpenAPI (Swagger), making batch management of multiple endpoints more efficient;
- The "Select from Discover" method is only available to "Enterprise Edition users". This method can automatically discover active APIs and generate endpoint recommendations based on actual traffic analysis, helping users manage API protection rules more easily.
Since I am not a distinguished "Enterprise Edition user", this article only covers two ways of adding endpoints: "manual addition" and "upload architecture".
2.1.3 "Manually add" endpoint operation
This section is based on myHome Data Center Series Cloudflare Worker + KV: Building WordPress Cloud Article Reading StatisticsThe API implemented by the Worker code in the article is added as an example. The specific Worker code is as follows:
export default {
async fetch(request, env) {
const url = new URL(request.url);
// 处理 GET 请求 -> 查询阅读次数
if (request.method === "GET" && url.pathname === "/views-track") {
return await handleGetRequest(url, env);
}
// 处理 POST 请求 -> 记录并返回最新阅读次数
if (request.method === "POST" && url.pathname === "/views-track") {
return await handlePostRequest(request, env);
}
return new Response("Invalid request", { status: 405 });
}
};
// 处理 GET 请求 -> 查询 KV 获取阅读量
async function handleGetRequest(url, env) {
const slug = url.searchParams.get("slug");
if (!isValidSlug(slug)) {
return new Response("Invalid slug format", { status: 400 });
}
const kvKey = `views:{slug}`;
const currentViews = parseInt(await env.views_kv.get(kvKey)) || 0;
return new Response(JSON.stringify({ success: true, views: currentViews }), {
headers: jsonHeaders(),
});
}
// 处理 POST 请求 -> 记录阅读量
async function handlePostRequest(request, env) {
try {
const { slug } = await request.json();
if (!isValidSlug(slug)) {
return new Response("Invalid slug format", { status: 400 });
}
const kvKey = `views:{slug}`;
const currentViews = parseInt(await env.views_kv.get(kvKey)) || 0;
await env.views_kv.put(kvKey, (currentViews + 1).toString());
return new Response(JSON.stringify({ success: true, views: currentViews + 1 }), {
headers: jsonHeaders(),
});
} catch (error) {
console.error("Worker Error:", error);
return new Response("Internal Server Error", { status: 500 });
}
}
// 校验 slug 格式
function isValidSlug(slug) {
return slug && /^[a-z0-9-]{1,100}$/.test(slug);
}
// 统一 JSON 响应头
function jsonHeaders() {
return {
"Content-Type": "application/json",
"Cache-Control": "no-store",
"CF-Cache-Status": "BYPASS",
};
}
From the above code, you can see that the access path of this API is "/views-track", and the methods are GET request (for querying article reading volume) and POST request (for recording reading volume). The host name is determined by the URL routing entry of the Worker, which is the domain name of my blog: "blog.tangwudi.com", so the final configuration of the endpoint is as follows:

Then, you can see the access status of the created endpoint:

You can also view further details:

Note 1: API Shield's endpoints are mainly used to define known requests for APIs (method + path + host name). However, it does not automatically intercept unmatched request methods. For example, even if an endpoint only adds GET requests, POST requests will not be directly blocked by API Shield and must be restricted with the help of WAF custom rules associated with the subsequent "failure settings".
Note 2: The "manually added" endpoint currently only defines the API request method (such as GET/POST) and path, but does not restrict the specific request content format, so there is still a certain risk of abuse. For example, in a GET request, the API expects the format to be /views-track?slug=xxx, but an attacker may send /views-track?slug= to write some random garbage data, causing the system to process invalid data or waste resources; in a POST request, the API expects the request body structure to be { "slug": "xxx" }, but an attacker may submit { "slug": 123 }, { "random_field": "hacker" }, or even an empty body, which may trigger an error or attempt to bypass restrictions. Therefore, relying solely on the "manually added" endpoint is not enough to define a fully compliant API request format. If you really want to be serious, you also need to limit the request content through "architecture validation" or WAF custom rules.
Note 3: For users who use WordPress to build websites, it is recommended to add the path "/wp-admin/admin-ajax.php" in the API Shield endpoint (select POST for the request method), because many themes and plug-ins (such as Rank Math SEO, WooCommerce, Lazy Load Image Plug-in, etc.) rely on this interface for AJAX interaction; in addition, if the website involves front-end interaction, such as likes, comment loading, form submission, or asynchronous data acquisition, admin-ajax.php is also essential, and most of these operations use the POST request method.
2.1.4 "Schema Validation" + "Upload Schema" (optional but highly recommended)
2.1.4.1 Advantages of Architecture Validation
Schema validation is not required for API Shield, but it is necessary when using Upload Schema When importing standardized API specification files such as OpenAPI (Swagger), it can provide Manually add endpoints More granular API protection.
As I mentioned earlier, manually added endpoints only define the Path + Method, but will not limit specific Request parameters, request body structure and data types, which means that attackers can still send malformed data, thereby affecting system stability or consuming resources.
The schema validation will strictly check whether the API request complies with Expected formatFor example, the "slug" field must be a string, not an integer; required fields cannot be missing or irrelevant fields cannot be included. If both the API provider and the caller follow the OpenAPI specification, schema validation can also ensure consistent data structure, avoid compatibility issues caused by incorrect parameter formats, and improve the stability and maintainability of the API.
In addition, schema validation can be used in conjunction with API Shield's "Failure Settings" and WAF rules to not only restrict request paths and methods, but also verify requests at the field, data type, and structure levels: If "Failure Settings" are enabled, unregistered API requests will be blocked by WAF rules, while schema validation ensures that the request format of registered APIs meets expectations, further enhancing API protection.
Therefore, if the API uses the standardized OpenAPI specification and wants to strictly verify the request format, enabling architecture validation will greatly improve security; but if the API does not use standard specifications, architecture validation is not a necessary step. In this case, WAF custom rules can be used to screen the request content.
To use architecture validation, you need an API architecture description file that complies with the OpenAPI specification. Take my cloud article statistics "/views-track" API as an example. The yml format file content of its architecture description is as follows for your reference:
openapi: 3.0.3 info: title: Views Tracking API description: API for tracking and retrieving article view counts. version: 1.0.0 servers: - url: https://blog.tangwudi.com description: Production server paths: /views-track: get: summary: Retrieve the view count of an article description: Fetches the current view count for a given article slug. parameters: - name: slug in: query required: true schema: type: string pattern: "^[a-z0-9-]{1,100}" responses: "200": description: Successfully retrieved the view count. content: application/json: schema: type: object properties: success: type: boolean example: true views: type: integer example: 123 "400": description: Invalid slug format. "405": description: Invalid request method. post: summary: Increment the view count of an article description: Increments the view count for a given article slug. requestBody: required: true content: application/json: schema: type: object properties: slug: type: string pattern: "^[a-z0-9-]{1,100}" responses: "200": description: Successfully updated the view count. content: application/json: schema: type: object properties: success: type: boolean example: true views: type: integer example: 124 "400": description: Invalid slug format. "500": description: Internal Server Error. "405": description: Invalid request method.
Save the above content as "views-track.yml" file, which will be used in the later practice.
In addition, umami's server API and random image API can be protected by architecture verification. Taking umami as an example, according to the description of the API in its official documentation, the corresponding API architecture file content is as follows (yml), and friends in need can use it directly (the url of the servers part needs to be modified according to your own website):
openapi: 3.0.1 info: title: Umami Tracking API description: API definition for Umami event tracking. version: 1.0.0 servers: - url: https://umami.tangwudi.com/api paths: /send: options: summary: Preflight request for CORS description: This allows browsers to check allowed methods before sending data. responses: "204": description: No content, preflight request successful. post: summary: Send data tracking description: Send analytics events and page views to Umami. requestBody: required: true content: application/json: schema: type: object properties: type: type: string enum: [event, pageview] description: Type of tracking data. payload: type: object description: Tracking payload containing event details. properties: website: type: string description: Website UUID. hostname: type: string description: Hostname of the site. screen: type: string description: Screen resolution of the client. language: type: string description: Language of the client browser. title: type: string description: Page title. url: type: string description: Page URL. responses: "200": description: Tracking data received successfully. "400": description: Bad request, invalid payload. "403": description: Forbidden request. "500": description: Internal server error.
2.1.4.2 "Architecture Verification" + "Architecture Upload" Practice
1. Enable schema authentication
Initially, schema authentication is disabled by default. You need to enable schema authentication:

2. Upload architecture
In "API Shield"-"Settings", upload the "views-track.yml" schema file:



Then you can already see the uploaded architecture in the "Uploaded Architecture" section:

At this time, in the schema validation section, you can see that the available schema after "/views-track" has become "views-track.yml", and you can also see how many non-compliant requests there are in the past 24 hours:

2.2 Failure Settings
As mentioned above, the endpoint part simply defines what the API allows. Path + Method, it does not automatically intercept unmatched request methods. To intercept unmatched request methods, you need to rely on the WAF custom rules created in the "Failure Settings" section:

Follow the steps below to associate a WAF custom rule in "Failure Settings":



After adding the rules of "admin-ajax.php", it looks like this:

Note 1: Failure settings are not automatically associated with WAF custom rules by default: If you add an endpoint manually for the first time, you need to manually create a failure rule based on the template; if you create an endpoint by uploading a schema file for the first time, Cloudflare will automatically generate the corresponding failure rule.
Note 2: In WordPress, in addition to the most commonly used API "/wp-admin/admin-ajax.php", there is also the API "/wp-json/*", which is used to Provides a REST-based data interaction interface, allowing plugins, themes, and external applications to access and manipulate WordPress content through standard HTTP requests (such as GET, POST, PUT, DELETE), such as obtaining articles, submitting comments, user authentication, etc.. However, compared to "admin-ajax.php", "/wp-json" is not very commonly used, because many plugins and themes still rely on traditional AJAX methods for data interaction, and REST API is frequently used mainly when developing custom applications or external integration. In addition, some sites may disable "/wp-json" for security reasons to reduce the exposure of API interfaces (such as me), so I did not add this API to the demonstration configuration. For friends who need this API, you need to consider the relevant configuration in the endpoint and failure settings.
2.3 Verification
Use the curl command to construct a request other than GET and POST to verify whether the policy set by "API Shield" is effective. If it is effective, the expected result is403 ForbiddenResponse, and there should be corresponding blocked request records in the "Failed Rules" of WAF in the Cloudflare dashboard.
1. Use PUT request method:
curl -X PUT "https://blog.tangwudi.com/views-track" -i

Then confirm in the "Failure Rules" of Cloudflare WAF custom rules whether there is a hit access request:

2. Use DELETE request method:
curl -X DELETE "https://blog.tangwudi.com/views-track" -i

Then confirm in the "Failure Rules" of Cloudflare WAF custom rules whether there is a hit access request:

Verification successful.
2.4 Other security configurations
The purpose of Cloudflare launching the "API Shield" feature is to provide security protection for existing APIs: pre-define legal API access methods, and then allow legal access and handle illegal access according to the pre-set method (failure rules) to achieve the purpose of protecting legal API access requests.
However, API access protection is not limited to "API Shield". There are also methods such as rate limiting, WAF custom rules (through conditions such as Referer), etc. Therefore, in actual applications, API protection is often combined with multiple methods. For example, rate limiting can prevent malicious users from frequently accessing the API and avoid resource abuse, while WAF custom rules can intercept based on specific request features (such as Referer, User-Agent, IP address, etc.) to prevent unauthorized or abnormal traffic.
In addition, you can also combine Cloudflare's Bot management function to identify and block automated crawlers or malicious attack scripts to further reduce the risk of API abuse. At the same time, using mTLS (two-way TLS authentication) or API Token for authentication can also ensure the compliance of API access at the source.
Therefore, in actual scenarios, using "API Shield" alone cannot cover all API protection needs. Instead, it needs to be combined with other means to form a complete API security protection system to minimize the risk of API abuse while ensuring stable access to normal business traffic.
3 Extended knowledge: F5 Distributed Cloud Robot Defense
I accidentally saw that F5 also has a solution to protect the user's API (the original address is as follows:Protect your Cloudflare CDN deployment with F5 Distributed CloudBot Defense), because of interest, I studied it:



In general, F5's solution is to use Cloudflare Worker for API protection, mainly by intercepting API requests through Worker, and then forwarding them to F5's API protection system for analysis and verification, and finally deciding whether to release, block or challenge based on the results returned by F5 API. The general process is as follows:
1. When an API request enters Cloudflare Worker, Worker is responsible for intercepting traffic and extracting key information such as request header and request body. The purpose of this step is to perform preliminary processing before the request reaches the origin API so that subsequent security detection can more accurately identify risks.
2. Worker will then send the extracted request data to F5's API protection system. F5 is responsible for in-depth analysis of this data, such as identifying whether the request comes from an automated bot, detecting malicious traffic, or verifying whether the token in the request is valid. Through these checks, F5 can determine whether the request meets security standards.
3. Finally, Worker will decide how to handle the request based on the analysis results returned by F5: if F5 considers the request to be legitimate, Worker will forward it to the origin API normally; but if F5 determines that the request is malicious traffic, Worker will directly return a 403 status code, or return a specific response based on custom rules to protect the API from attacks.
Simply put, if you have money, a large amount of API access, and need AI-level protection, you can use Worker + F5; if you don’t have money, Cloudflare API Shield is actually enough (at least you can use architecture validation).
Cloudflare Worker is not responsible for complex security analysis in this solution, but acts as a proxy. Its main work includes intercepting API requests, collecting necessary data, sending it to F5 for security testing, and deciding whether to release the request or directly intercept it based on F5's judgment. Worker itself does not perform in-depth security analysis, but relies on F5's security capabilities to complete this task.
The reason for choosing to implement it based on Worker is that Cloudflare WAF can only block requests based on predefined rules and lacks more flexible decision-making capabilities. Worker can make more complex judgments, such as identifying Bot behavior, analyzing user behavior patterns, etc. In addition, F5's API protection capabilities are stronger than Cloudflare WAF, but F5 cannot directly protect APIs hosted on Cloudflare. Therefore, Worker acts as an intermediate layer here to ensure that the API is protected by F5's security and to achieve smarter traffic management on Cloudflare's edge network.
4 Conclusion
In fact, strictly speaking,API Shield The core functions of WAF (such as only allowing specific request methods, specific paths, rate limiting, etc.) can be implemented by combining WAF custom rules with rate limiting functions. For example:
• Limit the request method: WAF rules can match http.request.method and only allow GET or POST.
• Limit the request path: WAF rules can match http.request.uri.path to ensure that API access is as expected.
• Limit the source of the request: You can set rules based on referer or IP to prevent unauthorized access.
• Rate Limiting:Cloudflare also provides WAF Rate Control, similar to the partial protection of API Shield.
The advantage of API Shield is that it integrates API protectionModularity and visualizationFor scenarios where there are a large number of APIs to manage, API Shield can reduce the workload of manual rule maintenance and further improve security in combination with mTLS (client certificate verification).
所以如果你的 API 保护需求比较简单,WAF 自定义规则就足够了,但如果是大规模 API 保护或者有更严格的安全要求,API Shield会让你更省心。