Rate Limiting
The vlrdevapi library includes built-in rate limiting to prevent overloading VLR.gg servers and to avoid getting blocked.
Default Configuration
By default, the library limits requests to 10 requests per second. This applies to:
Individual requests via
fetch_html()Concurrent requests via
batch_fetch_html()All API endpoints (matches, events, teams, players, etc.)
The rate limiter uses a sliding window algorithm that tracks recent request timestamps and automatically throttles requests when the limit is reached.
Configuring Rate Limits
You can adjust the rate limit to suit your needs:
# docs-validate: skip
import vlrdevapi as vlr
# Check current rate limit (0.0 means disabled)
current = vlr.get_rate_limit()
print(f"Current: {current} requests/second")
# Increase to 20 requests/second (enabled)
vlr.configure_rate_limit(requests_per_second=20.0, enabled=True)
# Decrease to 5 requests/second (more conservative)
vlr.configure_rate_limit(requests_per_second=5.0, enabled=True)
# Disable rate limiting (NOT recommended)
vlr.configure_rate_limit(enabled=False)
# Restore defaults (10 req/s, enabled)
vlr.reset_rate_limit()
How It Works
The rate limiter:
Tracks timestamps: Maintains a sliding window of the last 100 request timestamps
Calculates rate: Counts requests in the last 1 second
Throttles automatically: If limit is exceeded, waits until a request slot is available
Thread-safe: Works correctly with concurrent/parallel requests
Transparent: No code changes needed - works automatically
Example
import time
import vlrdevapi as vlr
# Set a conservative rate limit
vlr.configure_rate_limit(requests_per_second=2.0, enabled=True) # 2 requests/second
start = time.time()
# Make 5 requests - will automatically throttle
for i in range(5):
info = vlr.series.info(match_id=12345 + i)
print(f"Request {i+1} completed")
elapsed = time.time() - start
print(f"Total time: {elapsed:.1f}s")
# Expected: ~2.5 seconds for 5 requests at 2 req/s
Concurrent Requests
Rate limiting works seamlessly with batch fetching:
import vlrdevapi as vlr
# Set rate limit
vlr.configure_rate_limit(requests_per_second=10.0, enabled=True)
# Batch fetch respects rate limit
# Even though we use 4 workers, total rate won't exceed 10 req/s
matches = vlr.events.matches(event_id=2498, limit=20)
Best Practices
Recommended Settings:
Default (10 req/s): Good for most use cases
Conservative (5 req/s): For bulk scraping or long-running scripts
Aggressive (20 req/s): Only if you need faster responses and monitor for 429 errors
Guidelines:
Keep rate limiting enabled - Protects both you and the server
Monitor for 429 errors - If you get rate limited, decrease your limit
Lower for bulk operations - Use 5 req/s for large datasets
Test your limits - Start conservative, increase if needed
Respect the server - VLR.gg provides free data, don’t abuse it
Troubleshooting
Getting 429 (Rate Limited) errors?
# docs-validate: skip
# Decrease your rate limit
vlr.configure_rate_limit(requests_per_second=5.0, enabled=True)
Requests too slow?
# docs-validate: skip
# Check current setting
print(vlr.get_rate_limit())
# Increase cautiously
vlr.configure_rate_limit(requests_per_second=15.0, enabled=True)
Need to bypass for testing?
# docs-validate: skip
# Disable temporarily (use with caution)
vlr.configure_rate_limit(enabled=False)
# ... your test code ...
# Re-enable defaults
vlr.reset_rate_limit()
Technical Details
The rate limiter implementation:
Uses
threading.Lockfor thread safetyMaintains a
dequeof timestamps (max 100 entries)Calculates wait time based on oldest timestamp in the window
Sleeps the calling thread if rate limit is exceeded
Applies before each HTTP request in
fetch_html_with_retry()
This ensures consistent rate limiting across all API calls, whether sequential or concurrent.