TL;DR
Cloudflare APIs allow you to automate management of DNS, zones, Workers, security, and analytics. Use API tokens (recommended) for authentication, send HTTP requests to api.cloudflare.com/client/v4, and handle rate limits. For hands-on testing, leverage Apidog to validate DNS changes, test Worker deployments, and automate configuration workflows across environments.
Introduction
Cloudflare powers DNS, CDN, DDoS protection, WAF, and edge Workers for millions of sites. While the dashboard is fine for basic setups, larger or automated environments require API-driven workflows.
Cloudflare’s API supports all dashboard operations. You can programmatically create zones, manage DNS, deploy Workers, update SSL, and retrieve analytics.
Common developer use cases include:
- Infrastructure as code (Terraform, Pulumi)
- CI/CD pipeline integrations
- Managing multiple zones
- Automated DNS updates
- Worker deployment and management
💡 Pro tip: Apidog helps you test API requests, validate responses, and document your Cloudflare integration. Save and reuse zone configurations and share collections with your team.
Test Cloudflare APIs with Apidog — free.
By the end of this guide, you’ll be able to:
- Authenticate with Cloudflare API tokens
- Manage zones and DNS records
- Deploy and manage Workers
- Configure security settings
- Pull analytics and logs
Authentication
Cloudflare supports two authentication methods. Use API tokens for scoped permissions.
Method 1: API tokens (recommended)
API tokens restrict access to specific resources and actions.
To create a token:
- Go to Cloudflare Dashboard → My Profile → API Tokens
- Click "Create Token"
- Choose a template or define custom permissions (e.g., Edit zone DNS, Workers deployment)
- Set specific zones or select all zones
- Copy the generated token
Example usage:
curl -X GET "https://api.cloudflare.com/client/v4/user/tokens/verify" \
-H "Authorization: Bearer YOUR_API_TOKEN"
Method 2: Global API key (not recommended)
The global key gives full account access. Avoid using it unless absolutely necessary.
curl -X GET "https://api.cloudflare.com/client/v4/user" \
-H "X-Auth-Email: your-email@example.com" \
-H "X-Auth-Key: YOUR_GLOBAL_API_KEY"
Response format
All API responses follow this structure:
{
"result": { ... },
"success": true,
"errors": [],
"messages": []
}
Always check success before processing result.
Zone management
A zone in Cloudflare represents a domain.
List zones
curl -X GET "https://api.cloudflare.com/client/v4/zones" \
-H "Authorization: Bearer YOUR_API_TOKEN"
Sample response:
{
"result": [
{
"id": "023e105f4ecef8ad9ca31a8372d0c353",
"name": "example.com",
"status": "active",
"paused": false,
"type": "full",
"development_mode": 0,
"name_servers": [
"ns1.cloudflare.com",
"ns2.cloudflare.com"
],
"original_name_servers": [
"ns1.example.com"
],
"original_registrar": null
}
],
"success": true
}
Create a zone
curl -X POST "https://api.cloudflare.com/client/v4/zones" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "newdomain.com",
"account": {
"id": "ACCOUNT_ID"
},
"type": "full"
}'
Get zone details
curl -X GET "https://api.cloudflare.com/client/v4/zones/ZONE_ID" \
-H "Authorization: Bearer YOUR_API_TOKEN"
DNS record management
DNS records map domain names to IP addresses/services.
List DNS records
curl -X GET "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records" \
-H "Authorization: Bearer YOUR_API_TOKEN"
Create a DNS record
curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"type": "A",
"name": "www",
"content": "192.0.2.1",
"ttl": 3600,
"proxied": true
}'
Common record types:
-
A— IPv4 address -
AAAA— IPv6 address -
CNAME— Alias to another domain -
MX— Mail server -
TXT— Text records (SPF, DKIM, verification) -
NS— Name server
Update a DNS record
curl -X PUT "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records/RECORD_ID" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"type": "A",
"name": "www",
"content": "192.0.2.2",
"ttl": 3600,
"proxied": true
}'
Delete a DNS record
curl -X DELETE "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records/RECORD_ID" \
-H "Authorization: Bearer YOUR_API_TOKEN"
Cloudflare Workers
Workers let you run JavaScript at the edge.
List Workers
curl -X GET "https://api.cloudflare.com/client/v4/accounts/ACCOUNT_ID/workers/scripts" \
-H "Authorization: Bearer YOUR_API_TOKEN"
Upload a Worker
curl -X PUT "https://api.cloudflare.com/client/v4/accounts/ACCOUNT_ID/workers/scripts/my-worker" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/javascript" \
--data-binary @worker.js
Example Worker:
export default {
async fetch(request, env, ctx) {
const url = new URL(request.url)
if (url.pathname === '/api/hello') {
return new Response(JSON.stringify({ message: 'Hello from the edge!' }), {
headers: { 'Content-Type': 'application/json' }
})
}
return fetch(request)
}
}
Bind a route
curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/workers/routes" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"pattern": "example.com/api/*",
"script": "my-worker"
}'
Worker KV namespace
Store data accessible from Workers:
curl -X POST "https://api.cloudflare.com/client/v4/accounts/ACCOUNT_ID/storage/kv/namespaces" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "my-kv-namespace"
}'
Security and WAF
Page rules
curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/pagerules" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"targets": [
{
"target": "url",
"constraint": {
"operator": "matches",
"value": "example.com/*"
}
}
],
"actions": [
{
"id": "ssl",
"value": "flexible"
},
{
"id": "cache_level",
"value": "aggressive"
}
]
}'
Firewall rules
curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/firewall/rules" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"filter": {
"expression": "ip.geoip.country eq \"CN\"",
"paused": false
},
"action": "block",
"description": "Block traffic from China"
}'
Rate limiting
curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/rate_limits" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"disabled": false,
"description": "Rate limit API endpoints",
"match": {
"request": {
"methods": ["POST"],
"url_pattern": "*/api/*"
}
},
"threshold": 100,
"period": 60,
"action": {
"mode": "ban",
"timeout": 600
}
}'
Analytics and logs
Zone analytics
curl -X GET "https://api.cloudflare.com/client/v4/zones/ZONE_ID/analytics/dashboard?since=-1440&continuous=true" \
-H "Authorization: Bearer YOUR_API_TOKEN"
Sample response:
{
"result": {
"totals": {
"requests": {
"all": 1000000,
"cached": 800000,
"uncached": 200000
},
"bandwidth": {
"all": 50000000000,
"cached": 40000000000
},
"threats": {
"all": 5000
},
"pageviews": {
"all": 250000
}
}
}
}
Zone logs (Logpush)
Enable Logpush to stream logs to your storage:
curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/logpush/jobs" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "My Logpush Job",
"destination_conf": "s3://my-bucket/logs?region=us-east-1",
"dataset": "http_requests",
"logpull_options": "fields=ClientIP,ClientRequestPath,EdgeResponseStatus×tamps=rfc3339"
}'
Testing with Apidog
Cloudflare API changes affect live production traffic. Always test before deploying.
1. Environment setup
CLOUDFLARE_API_TOKEN: your_token
CLOUDFLARE_ACCOUNT_ID: abc123
ZONE_ID: xyz789
BASE_URL: https://api.cloudflare.com/client/v4
2. Validate responses
pm.test('Request was successful', () => {
const response = pm.response.json()
pm.expect(response.success).to.be.true
pm.expect(response.errors).to.be.empty
})
pm.test('DNS record created correctly', () => {
const response = pm.response.json()
pm.expect(response.result.type).to.eql('A')
pm.expect(response.result.name).to.eql('www')
pm.expect(response.result.proxied).to.be.true
})
3. Test Worker deployments
Save Worker scripts in Apidog and test uploads:
pm.test('Worker uploaded', () => {
const response = pm.response.json()
pm.expect(response.result.id).to.eql('my-worker')
})
Test Cloudflare APIs with Apidog — free.
Common errors and fixes
403 Forbidden
Cause: Token lacks required permissions.
Fix: Check token permissions in Cloudflare dashboard. DNS edits require Zone:DNS:Edit. Workers require Account:Workers:Edit.
1003: Invalid or missing zone
Cause: Zone ID is incorrect or inaccessible.
Fix: Verify the zone ID and ensure the token’s scope includes the target zone.
81057: Record already exists
Cause: DNS record with same type/name exists.
Fix: Use PUT to update, or DELETE before POST.
Rate limit exceeded
Cause: Too many requests (default: 1200/5min).
Fix: Implement backoff and batch API operations.
async function updateRecords(records) {
for (const record of records) {
try {
await updateRecord(record)
await sleep(100) // Rate limit buffer
} catch (error) {
if (error.status === 429) {
await sleep(60000) // Wait a minute
await updateRecord(record)
}
}
}
}
Alternatives and comparisons
| Feature | Cloudflare | AWS Route 53 | Fastly |
|---|---|---|---|
| DNS API | ✓ | ✓ | ✓ |
| CDN API | ✓ | CloudFront API | ✓ |
| Edge functions | Workers | Lambda@Edge | Compute@Edge |
| WAF API | ✓ | AWS WAF | ✓ |
| Free tier | Generous | Pay per use | Limited |
| Response format | JSON | XML/JSON | JSON |
Cloudflare’s API is more unified than AWS’s fragmented services. Workers offer more edge flexibility than Lambda@Edge.
Real-world use cases
Multi-tenant SaaS: Automatically create Cloudflare zones as new customer domains are added. Use the API for Workers deployment, DNS record creation, and certificate provisioning.
Blue-green deployments: Update DNS records via API to switch production traffic between environments with instant Cloudflare propagation.
DDoS response automation: Monitor via analytics API, then use the API to add firewall rules and block malicious IPs in real time.
Wrapping up
Key takeaways:
- Use API tokens for scoped, secure authentication
- Automate zone and DNS management
- Deploy and manage Workers at the edge
- Configure security (WAF, firewall, rate limiting)
- Retrieve analytics and configure log shipping
- Test all API workflows with Apidog before going live
FAQ
What’s the difference between a zone and a domain?
A zone is Cloudflare’s representation of a domain. When you add a domain, you create a zone. Use the zone ID in API requests.
How do I find my zone ID?
Cloudflare Dashboard → select your domain → Overview → API section.
Can I use Cloudflare API without a paid plan?
Yes. Most features work on free plans. Some advanced features (e.g., Logpush) require paid plans.
How long do DNS changes take?
API changes update Cloudflare instantly. Global propagation depends on TTL and DNS resolvers, usually minutes.
What’s the rate limit?
Default: 1200 requests per 5 minutes per token. Check the X-RateLimit-Remaining header. Higher limits for enterprise.
Can I manage multiple accounts with one token?
No. Tokens are per account. Create separate tokens or use user-level tokens with access to multiple accounts.
How do Workers differ from Lambda?
Workers run at Cloudflare’s edge (300+ locations), not in specific AWS regions. Cold starts are negligible. Suited for fast request/response logic.
Can I use the API to purge cache?
Yes:
curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/purge_cache" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"files": ["https://example.com/style.css"]
}'

Top comments (0)