DEV Community

Cover image for How to Use Cloudflare APIs?
Wanda
Wanda

Posted on • Originally published at apidog.com

How to Use Cloudflare APIs?

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.

Try Apidog today

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:

  1. Go to Cloudflare Dashboard → My Profile → API Tokens
  2. Click "Create Token"
  3. Choose a template or define custom permissions (e.g., Edit zone DNS, Workers deployment)
  4. Set specific zones or select all zones
  5. Copy the generated token

Example usage:

curl -X GET "https://api.cloudflare.com/client/v4/user/tokens/verify" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

Response format

All API responses follow this structure:

{
  "result": { ... },
  "success": true,
  "errors": [],
  "messages": []
}
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

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"
  }'
Enter fullscreen mode Exit fullscreen mode

Get zone details

curl -X GET "https://api.cloudflare.com/client/v4/zones/ZONE_ID" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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
  }'
Enter fullscreen mode Exit fullscreen mode

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
  }'
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)
  }
}
Enter fullscreen mode Exit fullscreen mode

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"
  }'
Enter fullscreen mode Exit fullscreen mode

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"
  }'
Enter fullscreen mode Exit fullscreen mode

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"
      }
    ]
  }'
Enter fullscreen mode Exit fullscreen mode

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"
  }'
Enter fullscreen mode Exit fullscreen mode

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
    }
  }'
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

Sample response:

{
  "result": {
    "totals": {
      "requests": {
        "all": 1000000,
        "cached": 800000,
        "uncached": 200000
      },
      "bandwidth": {
        "all": 50000000000,
        "cached": 40000000000
      },
      "threats": {
        "all": 5000
      },
      "pageviews": {
        "all": 250000
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

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&timestamps=rfc3339"
  }'
Enter fullscreen mode Exit fullscreen mode

Testing with Apidog

Cloudflare API changes affect live production traffic. Always test before deploying.

Apidog Cloudflare Testing

1. Environment setup

CLOUDFLARE_API_TOKEN: your_token
CLOUDFLARE_ACCOUNT_ID: abc123
ZONE_ID: xyz789
BASE_URL: https://api.cloudflare.com/client/v4
Enter fullscreen mode Exit fullscreen mode

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
})
Enter fullscreen mode Exit fullscreen mode

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')
})
Enter fullscreen mode Exit fullscreen mode

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)
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

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"]
  }'
Enter fullscreen mode Exit fullscreen mode

Top comments (0)