Overview
The CoW Protocol API enforces rate limits to ensure fair access and protect infrastructure. Key points:
- Different endpoints have different limits based on computational cost
- Limits apply per IP address
- Exceeding limits returns an HTTP
429 Too Many Requests response
- There is no API key system — all access is unauthenticated and rate-limited per IP
Rate limits are designed to support normal integration patterns. If you are consistently hitting limits, consider optimizing your request patterns using the best practices below.
Per-Endpoint Limits
| Endpoint | Method | Limit | Window | Notes |
|---|
/api/v1/quote | POST | 10 req/s | Per second | Most restrictive — triggers solver computation |
/api/v1/orders | POST | 5 req/s | Per second | Order submission |
/api/v1/orders/{uid} | GET | 100 req/min | Per minute | Order status polling |
/api/v1/orders/{uid} | DELETE | 5 req/s | Per second | Order cancellation |
/api/v1/trades | GET | 100 req/min | Per minute | Trade history |
/api/v1/auction | GET | 30 req/min | Per minute | Auction data |
| General read endpoints | GET | 100 req/min | Per minute | Default for other GET endpoints |
The /api/v1/quote endpoint is the most expensive because each request triggers a full solver computation cycle. CoW Protocol runs batch auctions every ~15 seconds, so there is rarely a reason to request quotes more frequently than once per 15 seconds for the same trading pair. Avoid unnecessary quote requests by caching results and only refreshing when input parameters change.
Firewall Protection (Cloudflare)
In addition to API-level rate limits, the CoW Protocol API is protected by a Cloudflare Web Application Firewall (WAF). This means:
- You may receive an HTTP 403 Forbidden response from Cloudflare before reaching the API rate limiter
- Cloudflare’s rules are dynamic and may be more aggressive than the published per-endpoint limits, particularly for the
/api/v1/quote endpoint
- Repeated violations or unusual request patterns can trigger IP-level blocks that persist beyond individual rate limit windows
If you receive 403 responses despite staying well under the published rate limits, your IP may have been flagged by Cloudflare. This is distinct from a 429 rate limit response. See Troubleshooting for how to resolve this.
How to distinguish the two
| Response | Source | Meaning |
|---|
| 429 Too Many Requests | CoW Protocol API | You exceeded per-endpoint rate limits. Retry after the Retry-After header value. |
| 403 Forbidden | Cloudflare WAF | Your IP has been flagged. Contact the team to resolve (see Getting Help). |
When you exceed a rate limit, the API responds with:
- HTTP 429 Too Many Requests status code
Retry-After header indicating the number of seconds until your next request will be accepted
HTTP/1.1 429 Too Many Requests
Retry-After: 2
Content-Type: application/json
{
"errorType": "TooManyRequests",
"description": "Rate limit exceeded. Please retry after 2 seconds."
}
SDK Built-in Rate Limiting
The official SDKs include built-in rate limiting so you don’t have to implement it yourself:
- TypeScript SDK — ships with a default limiter set to 5 requests/second
- cow-py (Python) — includes automatic backoff and retry strategies for all API calls
Using an official SDK is the recommended approach for most integrations, as it handles rate limiting, retries, and request formatting out of the box.
Backoff Strategy
If you are calling the API directly (without an SDK), always implement retry logic with exponential backoff and jitter to handle rate limit responses gracefully.
Exponential Backoff with Jitter (TypeScript)
async function fetchWithBackoff(
url: string,
options: RequestInit,
maxRetries = 3
): Promise<Response> {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fetch(url, options)
if (response.status !== 429) return response
const retryAfter = response.headers.get('Retry-After')
const baseDelay = retryAfter
? parseInt(retryAfter) * 1000
: Math.pow(2, attempt) * 1000
const jitter = Math.random() * 1000
await new Promise((r) => setTimeout(r, baseDelay + jitter))
}
throw new Error('Rate limited after max retries')
}
Exponential Backoff with Jitter (Python)
import time
import random
import requests
def fetch_with_backoff(url, payload=None, max_retries=3):
for attempt in range(max_retries):
resp = (
requests.post(url, json=payload)
if payload
else requests.get(url)
)
if resp.status_code != 429:
return resp
retry_after = int(resp.headers.get("Retry-After", 2**attempt))
time.sleep(retry_after + random.random())
raise Exception("Rate limited after max retries")
Best Practices by Integration Type
Frontend / dApp
- Cache quotes for UI display — only refresh when the user changes input parameters
- Show a loading state during quote fetches to prevent duplicate requests
- Do not poll order status more than once every 5 seconds
- Debounce user input before triggering quote requests
Backend / Bot
- Implement a request queue with built-in rate limiting
- CoW Protocol runs auctions every ~15 seconds — polling quotes faster than this provides no benefit
- Batch operations where possible to reduce total request count
- Track your request rate client-side to stay under limits proactively
- Consider sourcing prices from another provider (e.g., a DEX aggregator or your own pricing system) and only using the CoW Protocol API for order submission, which has more generous limits
Aggregator
- Rate limits apply per IP — if running multiple instances behind the same IP, coordinate request budgets across them
- Consider using the TypeScript SDK which handles rate limiting internally
- For production aggregator integrations that need elevated throughput, contact bd@cow.fi
Rate limits are the same across all supported networks (Mainnet, Gnosis Chain, Arbitrum, Base, and Sepolia). Each network’s API is rate-limited independently.
Troubleshooting
| Symptom | Likely Cause | Solution |
|---|
| Getting 429 but request volume seems low | Retry loops or concurrent requests from the same IP | Add backoff logic; check for runaway retry loops |
| Getting 403 despite low request volume | Cloudflare WAF has flagged your IP | Contact the team (see Getting Help) |
| Quotes are slow to return | Near the rate limit threshold | Space out requests; cache results more aggressively |
| Order submission fails intermittently | Hitting submission limits during batch operations | Queue submissions and throttle to under 5 req/s |
| Multiple services share the same IP | Combined traffic exceeds per-IP limits | Coordinate request budgets or use separate IPs |
| Blocked on first request to a new endpoint | IP reputation or shared hosting/VPN | Try from a different IP, or contact the team |
Getting Help
There is currently no self-service API key system for custom rate limits. If you need elevated limits or are experiencing unexpected blocks:
- Email: Contact bd@cow.fi with your use case and expected request volume
- Discord: Join the CoW Protocol Discord and reach out in the tech-talk channel
- Feedback: Use the feedback button on swap.cow.fi (bottom-right corner) to report API access issues
When reporting an issue, include your public IP address and the HTTP status code you’re receiving (429 vs. 403) so the team can investigate quickly.