Rate Limiting
Cap requests per IP, globally or per path
Rate limits are enforced per IP using a token-bucket algorithm. Configure a global limit plus per-path overrides for endpoints that need tighter or looser caps.
How it works
Every incoming request consumes a token from a bucket keyed by
ip + path. Tokens refill at a steady rate (requests per second).
If the bucket is empty, the request is rejected with
429 Too Many Requests.
The burst value sets the bucket size — how many requests can fire in a quick spike before the steady rate kicks in. Think of it as a short-term allowance on top of the sustained rate.
Configuration
Sidebar → Firewall → Rate Limiting card:
Global defaults
| Field | Default | Notes |
|---|---|---|
| Requests per second | 50 | Sustained per-IP rate across all paths |
| Burst | 100 | Spike allowance before throttling |
These apply to any path that doesn't have a specific override below.
Per-path overrides
Add path-specific limits for endpoints with different traffic profiles. The proxy matches the request path using prefix matching — the first matching pattern wins.
| Field | Notes |
|---|---|
| Pattern | URL prefix to match (e.g. /c, /player_api.php) |
| Requests/sec | Sustained limit for this path |
| Burst | Spike allowance for this path |
Recommended path limits
Device portal — /c
The /c endpoint is called by MAG/STB devices for portal loading,
channel switching, and EPG refresh. It's also the most common target
for scraping bots.
{
"pattern": "/c",
"requests_per_second": 20,
"burst": 60
}Why 20 req/s? One device makes 1-3 req/s when channel surfing. But a single IP can have multiple devices behind NAT — a household with 3 MAG boxes peaks at ~9 req/s, a hotel or CGNAT with 6+ devices can hit 15-20 req/s legitimately. Setting 20 covers these cases while catching bots that hammer at 50-100+ req/s.
Why burst 60? When a MAG box boots, it fires 8-15 requests in ~2 seconds (portal, channels, EPG, logos). Multiple devices booting at once (e.g. after a power outage) can mean 3-4 devices x 15 requests = ~50 burst. A burst of 60 gives headroom.
[!info] For per-device protection on
/c, enable MAC Protection alongside this path rate limit. IP rate limiting catches single-IP floods (cheap check). MAC protection catches smarter bots that distribute across IPs but cycle through device MACs.
Player API — /player_api.php
{
"pattern": "/player_api.php",
"requests_per_second": 20,
"burst": 40
}The player API handles authentication and channel listing. Typical usage is a burst on app launch followed by occasional refreshes.
Playlist — /get.php
{
"pattern": "/get.php",
"requests_per_second": 2,
"burst": 5
}M3U playlist download — typically 50MB+ payload. Real apps fetch 1-2 times per day and cache locally. Bots hammer this endpoint to keep stolen catalogs fresh. Tight limit is safe since there's no legitimate reason to hit it multiple times per second.
EPG — /xmltv.php
{
"pattern": "/xmltv.php",
"requests_per_second": 1,
"burst": 3
}EPG XML download — often larger than the playlist. Real apps fetch once per day. Locking this down stops EPG mirroring bots.
Admin/Panel API — /panel_api.php
{
"pattern": "/panel_api.php",
"requests_per_second": 5,
"burst": 10
}If your panel exposes this, it's a high-privilege endpoint (resellers, account management). Lock it down hard — even legitimate admin use shouldn't burst beyond 10 requests.
Paths you should NOT rate limit
| Path | Why not |
|---|---|
/play, /live/, /movie/, /series/, /timeshift/ | Streaming endpoints — 1 request = long-lived connection. Rate limits do nothing. |
/hls/, *.m3u8, *.ts | HLS segments — bursty by design. Global default handles it. |
/logo/, /picons/ | High volume, tiny files. Global default is enough. |
For these, the abuse vector is concurrent stream count or token hotlinking, not request rate. See Recommended Settings for what these problems actually need.
Layered defense with MAC protection
IP rate limiting and MAC protection
work together on device endpoints like /c:
| Attack | What catches it |
|---|---|
| Bot at 100 req/s from 1 IP | IP rate limit (20 req/s cap) |
| Bot at 15 req/s from 1 IP, 1 MAC | Passes IP limit → MAC rate limit (3 req/s per MAC) |
| Bot at 2 req/s from 1 IP, cycling 100 MACs | Passes both rate limits → MAC-per-IP tracking (>25 unique MACs = ban) |
| Bot at 2 req/s, distributed across many IPs, 1 MAC each | Passes IP + MAC-per-IP → per-MAC rate limit catches repeated MAC |
| Real user, 1 MAC, 1-2 req/s | Passes everything |
Whitelist
IPs in the firewall whitelist bypass all rate limiting (and every other firewall check). Use this for monitoring, load balancers, or known high-traffic customers.
Interaction with other firewall rules
The order of checks per request:
- Image redirect → bypass
- Whitelist hit → bypass everything below
- Banned IP →
403 - VPN/proxy check →
403if flagged - Rate limit →
429if over limit - MAC protection →
403if MAC invalid or rate exceeded - Country block →
403if blocked - Forward to backend
Rate limiting runs before MAC protection. This means a single-IP flood is caught early (cheap check) before the more granular per-MAC logic runs.
Tuning
False positives (real users getting 429s)
- Raise
burst— if users see errors during app startup, the boot spike exceeds the burst allowance - Raise
requests_per_secondon the specific path — the sustained rate is too tight - Whitelist the IP — if it's a known good actor (monitoring, business customer with heavy traffic)
False negatives (bots slipping through)
- Lower path-specific limits — bots are staying under the global rate
- Add path overrides for the endpoints being targeted
- Enable auto-ban — repeated rate limit violations trigger a temporary IP ban
- Enable MAC protection on device endpoints — catches bots that IP rate limiting alone can't