I keep getting 429 when trying to download subtitles via API. I’m on the Basic plan with 50rps and 15k downloads per 24h. Does the download server have a separate rate limit? If so, would you mind sharing what it is? Thank you.
Anecdotally, I’m not even able to download at a rate of 5 per second. Code:
const res = await fetch(response.link, {
headers: { ‘Api-Key’: apiKey, ‘User-Agent’: USER_AGENT },
});
Hi Ilya,
Thank you for reaching out. On the Basic plan you should indeed have 50 requests per second available, so hitting 429 at only 5/sec is unexpected.
A few things to check:
First, please look at the rate limit headers in your responses — they’ll tell you what the server is actually seeing:
x-ratelimit-limit-second
x-ratelimit-remaining-second
ratelimit-reset
This will help clarify whether the server is recognising your Basic plan limits or applying defaults. Also note that the rate limit applies mostly to search — the download endpoint may behave differently since it generates temporary links with an expiry.
For more details on rate limiting and headers, please see our Getting Started guide: https://opensubtitles.stoplight.io/docs/opensubtitles-api/e3750fd63a100-getting-started
To help us debug further, could you share some logs showing the full response headers from a few consecutive download requests? That way we can see exactly what limits are being applied and what’s triggering the 429.
Thanks for your reply. Here’s a sample request and response:
Request GET:
https://www.opensubtitles.com/download/2747C3F3F93F161E372F6F3C3A758B8CBF2C36472936038EDDFD1E1D77C6F322599577E815515CDF6E2472B048DE98051814FB1E39AEAD5920ED03FFE01ADCA73ABD38902BC65E407517D38B4B6C79736755E70271A244A5610D85AA63978100A3FA72FEEC99F7FAEED6AF878AB324291BBEF007F0B9545D31257839459A4404CCBEB22D87D3DD3B9B780FFE0011A9E3BE6D90F7249EF7AC90A1F50010F14CE358CB85FF4D3E4FC7390A4CAA7CCC5E5770B2B41A60EF73F34F7FC98E1636D56AD0F98349255538E9C691E1C8CDF724F407F58A91B039D765C2C5E7478B4AD336AE239738B0FDF2B67DAC773395070D46F908CB599250AD053ADADF260857C98671EF28328F44AB220FA350A5553C29A42E19393A5209342B/subfile/Le%20roi%20lion%202.srt
Request headers:
{
"Api-Key": "<redacted>",
"User-Agent": "<redacted> v0.0.1"
}
Response headers:
{
"access-control-allow-origin": "*",
"age": "238",
"alt-svc": "h3=\":443\"; ma=86400",
"cache-control": "public, max-age=3155695200",
"cf-cache-status": "HIT",
"cf-ray": "9e1494034ea5da21-CDG",
"connection": "keep-alive",
"content-encoding": "br",
"content-security-policy": "default-src 'self'; font-src 'self' fonts.googleapis.com code.cdn.mozilla.net https: data:; img-src 'self' image.tmdb.org m.media-amazon.com ia.media-imdb.com https: data:; object-src 'self' forum.opensubtitles.com embed.tawk.to; form-action 'self' forum.opensubtitles.com localhost:4200 www.opensubtitles.com tst.yabo-concept.ch ai.opensubtitles.com; frame-src 'self' sbl.onfastspring.com opensubtitles.stoplight.io *.opensubtitles.com opensubtitles.tawk.help forum.opensubtitles.com opensubtitles.test.onfastspring.com opensubtitles.onfastspring.com *.cloudfront.net api.blink.net *.tawk.to tawk.to test.blink.net blink.net www.recaptcha.net www.google.com www.youtube.com sender.cleverwebserver.com c.clvrads.com; connect-src 'self' srv.tunefindforfans.com region1.google-analytics.com bam.eu01.nr-data.net opensubtitles.test.onfastspring.com opensubtitles.onfastspring.com *.cloudfront.net rb-dev:8082 cana.local:8082 localhost:8082 *.test.resolver.perfops.net *.tawk.to wss://*.tawk.to cdn.datatables.net www.google-analytics.com www.gstatic.com https://cdn.datatables.net; base-uri 'self' test.blink.net api.blink.net blink.net *.blink.net; frame-ancestors 'self' forum.opensubtitles.com opensubtitles.onfastspring.com opensubtitles.test.onfastspring.com; script-src 'self' *.cloudfront.net srv.tunefindforfans.com bam.eu01.nr-data.net www.google.com cdn.datatables.net www.recaptcha.net www.google-analytics.com sender.cleverwebserver.com https: 'unsafe-inline' 'unsafe-eval'; style-src 'self' cdnjs.cloudflare.com https: 'unsafe-inline'",
"content-type": "text/plain; charset=utf-8",
"date": "Tue, 24 Mar 2026 09:16:38 GMT",
"etag": "W/\"889099b8e1880bb40185f994ebd20308\"",
"last-modified": "Sat, 01 Jan 2011 00:00:00 GMT",
"nel": "{\"report_to\":\"cf-nel\",\"success_fraction\":0.0,\"max_age\":604800}",
"referrer-policy": "strict-origin-when-cross-origin",
"report-to": "{\"group\":\"cf-nel\",\"max_age\":604800,\"endpoints\":[{\"url\":\"https://a.nel.cloudflare.com/report/v4?s=faqdTWQQFodhZNU10%2Fp0K7X3zxZp7300ZvVJj8vq%2Fqga1k5pNXEKhBqNkHbjxCGhI2bNoVPUhjWvnCAnss5%2Bh8aj7WSlEj0c7Yof2BiRaxti4KoxnQ%3D%3D\"}]}",
"server": "cloudflare",
"strict-transport-security": "max-age=15552000; includeSubDomains; preload",
"transfer-encoding": "chunked",
"vary": "Accept",
"x-cache-backend": "rb2",
"x-content-type-options": "nosniff",
"x-debug-method": "GET",
"x-debug-url": "/download/2747C3F3F93F161E372F6F3C3A758B8CBF2C36472936038EDDFD1E1D77C6F322599577E815515CDF6E2472B048DE98051814FB1E39AEAD5920ED03FFE01ADCA73ABD38902BC65E407517D38B4B6C79736755E70271A244A5610D85AA63978100A3FA72FEEC99F7FAEED6AF878AB324291BBEF007F0B9545D31257839459A4404CCBEB22D87D3DD3B9B780FFE0011A9E3BE6D90F7249EF7AC90A1F50010F14CE358CB85FF4D3E4FC7390A4CAA7CCC5E5770B2B41A60EF73F34F7FC98E1636D56AD0F98349255538E9C691E1C8CDF724F407F58A91B039D765C2C5E7478B4AD336AE239738B0FDF2B67DAC773395070D46F908CB599250AD053ADADF260857C98671EF28328F44AB220FA350A5553C29A42E19393A5209342B/subfile/Le%20roi%20lion%202.srt",
"x-debug-vcl-deliver": "RUNNING",
"x-download-options": "noopen",
"x-frame-options": "SAMEORIGIN",
"x-permitted-cross-domain-policies": "none",
"x-ratelimit-limit-minute": "240",
"x-ratelimit-limit-second": "6",
"x-ratelimit-remaining-minute": "1196",
"x-ratelimit-remaining-second": "2",
"x-ratelimit-source": "varnish",
"x-request-id": "c5fe6c20-4deb-4386-8b25-8f9134ea9cb6",
"x-runtime": "0.012676",
"x-var-cache": "MISS",
"x-vcl-version": "2026-02-07-v7",
"x-via": "lb1",
"x-xss-protection": "1; mode=block"
}
I see the following rate-limit response headers:
x-ratelimit-limit-minute: 240
x-ratelimit-limit-second: 6
x-ratelimit-remaining-minute: 1196
x-ratelimit-remaining-second: 2
x-ratelimit-source: varnish
One thing that caught my eye: How can I have 240 per minute, but also have 1196 remaining for the minute? For downloads, there was no ratelimit-reset.
For the rest of the API, I get x-ratelimit-limit-second: 50.
Does this mean that, even with a Basic plan, there’s a 6RPS limit for downloading subtitles? Are the two rate limits (and endpoints) completely separate?
Thanks again.
Thanks for the detailed logs — that’s really helpful.
So the key thing here is that the download URL you’re calling (the long /download/... URL) is not part of the API itself. That URL is generated by the /download API endpoint, and then it’s served and cached through Cloudflare/Varnish — there’s no authorization check on it, it’s just a static file link at that point.
The rate limit headers you’re seeing on those download URLs (x-ratelimit-limit-second: 6, x-ratelimit-source: varnish) are from the Varnish caching layer, not from our API. That’s separate from your API plan limits — which is why you see 50rps on actual API calls but 6rps on the file downloads.
As for the x-ratelimit-remaining-minute: 1196 being higher than the 240 limit — that looks like a quirk of the Varnish/caching layer reporting, not something we control on the API side.
So to summarize: yes, the API rate limit and the download file serving are completely separate. Your Basic plan 50rps applies to API calls (search, /download endpoint to generate the link, etc.), while the actual file download URLs go through a different layer with its own limits.
If you’re hitting 429s on the file downloads specifically, try pacing those requests to stay within the limits shown in the Varnish headers.
Understood. Thanks for the clarification!