The documentation for the Login method says:
If response code is
401 Unathorized
stop sending further requests with the same credentials, login is “expensive” operation.Request rate limit is 1 request per 1 second.
Side note: Unathorized should be: Unauthorized
Side note: login is “expensive” operation should be: login is an “expensive” operation
Makes sense that the server rate limits failing login requests. However upon successful login the server is returning:
ratelimit-reset: 1
ratelimit-remaining: 0
ratelimit-limit: 1
That indicates the request quota in the current time window has been used up and the client must wait one second before making another request.
Is this intended? Do clients have to wait after a successful login before sending a subtitle search request?
Full output from login test:
low-batt@gag ~$ curl -vvv --location 'https://api.opensubtitles.com/api/v1/login' \
> --header 'Accept: */*' \
> --header 'Content-Type: application/json' \
> --header 'Api-Key: <REDACTED>' \
> --user-agent '<REDACTED>' \
> --data '{"username": "<REDACTED>", "password": "<REDACTED>"}'
* Trying 172.64.163.3:443...
* Connected to api.opensubtitles.com (172.64.163.3) port 443 (#0)
* ALPN: offers h2,http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
* CAfile: /etc/ssl/cert.pem
* CApath: none
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* (304) (IN), TLS handshake, CERT verify (15):
* (304) (IN), TLS handshake, Finished (20):
* (304) (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / AEAD-CHACHA20-POLY1305-SHA256
* ALPN: server accepted h2
* Server certificate:
* subject: CN=opensubtitles.com
* start date: Oct 4 11:01:43 2023 GMT
* expire date: Jan 2 11:01:42 2024 GMT
* subjectAltName: host "api.opensubtitles.com" matched cert's "*.opensubtitles.com"
* issuer: C=US; O=Google Trust Services LLC; CN=GTS CA 1P5
* SSL certificate verify ok.
* using HTTP/2
* h2 [:method: POST]
* h2 [:scheme: https]
* h2 [:authority: api.opensubtitles.com]
* h2 [:path: /api/v1/login]
* h2 [user-agent: <REDACTED>]
* h2 [accept: */*]
* h2 [content-type: application/json]
* h2 [api-key: <REDACTED>]
* h2 [content-length: 60]
* Using Stream ID: 1 (easy handle 0x121011400)
> POST /api/v1/login HTTP/2
> Host: api.opensubtitles.com
> User-Agent: <REDACTED>
> Accept: */*
> Content-Type: application/json
> Api-Key: <REDACTED>
> Content-Length: 60
>
* We are completely uploaded and fine
< HTTP/2 200
< date: Thu, 05 Oct 2023 18:51:08 GMT
< content-type: application/json; charset=utf-8
< content-length: 315
< x-ratelimit-remaining-hour: 59
< x-ratelimit-limit-hour: 60
< ratelimit-reset: 1
< ratelimit-remaining: 0
< ratelimit-limit: 1
< x-ratelimit-remaining-second: 0
< x-ratelimit-limit-second: 1
< x-frame-options: SAMEORIGIN
< x-xss-protection: 1; mode=block
< x-content-type-options: nosniff
< x-download-options: noopen
< x-permitted-cross-domain-policies: none
< referrer-policy: strict-origin-when-cross-origin
< cache-control: max-age=0, private, must-revalidate, s-maxage=600
< access-control-allow-origin: *
< access-control-allow-methods: GET, HEAD, POST, OPTIONS
< access-control-allow-headers: Origin, Authorization, Accept, Api-Key, Content-Type, X-User-Agent
< 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'; form-action 'self' forum.opensubtitles.com localhost:4200 www.opensubtitles.com; frame-src 'self' 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; connect-src 'self' region1.google-analytics.com bam.eu01.nr-data.net opensubtitles.test.onfastspring.com opensubtitles.onfastspring.com *.cloudfront.net rb-dev:8082 *.tawk.to wss://*.tawk.to cdn.datatables.net www.google-analytics.com test.blink.net api.blink.net blink.net www.gstatic.com *.blink.net api.test.blink.net; base-uri 'self' test.blink.net api.blink.net blink.net *.blink.net; frame-ancestors 'self'; script-src 'self' *.cloudfront.net bam.eu01.nr-data.net www.google.com cdn.datatables.net www.recaptcha.net www.google-analytics.com https: 'unsafe-inline' 'unsafe-eval'; style-src 'self' cdnjs.cloudflare.com https: 'unsafe-inline'
< x-request-id: 990fe2b5-2fc5-4872-990b-9137cadb4a19
< x-runtime: 0.425481
< x-stackifyid: V1|c62650a5-81f6-4fa6-ae94-d89e16d52e74|C98184|CD5
< x-kong-upstream-latency: 2863
< x-kong-proxy-latency: 3
< x-cache-backend: apigw1_8000 rb1
< age: 0
< x-var-cache: MISS
< x-via: fw1
< accept-ranges: bytes
< cf-cache-status: DYNAMIC
< report-to: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=MsnFXf3kp2bxAJQrGWiIwuQtKHmTYTaoEjN6E%2B%2Fs2NoNqa0pc7uIa5LKVLx56qk1EE2mLW1jd79aGiupaSh40UtIHwD3VebAXaospi4cPXIAz4xsoKgHCX%2BSjszYYwjwqmoQ3dh%2FhZo%3D"}],"group":"cf-nel","max_age":604800}
< nel: {"success_fraction":0,"report_to":"cf-nel","max_age":604800}
< strict-transport-security: max-age=15552000; includeSubDomains; preload
< server: cloudflare
< cf-ray: 8117daa1eb128cda-EWR
< alt-svc: h3=":443"; ma=86400
<
* Connection #0 to host api.opensubtitles.com left intact
{"user":{"allowed_translations":1,"allowed_downloads":20,"level":"Sub leecher","user_id":<REDACTED>,"ext_installed":false,"vip":false},"token":"<REDACTED>","status":200}
low-batt@gag ~$