Read the message, not just the number
The form displays the returned error.message. An API response also includes error.code. These are the three 429 branches in the inspected source—not a claim that every production 429 must use this JSON shape.
| Code | Exact message | What to distinguish |
|---|---|---|
DAILY_LIMIT_REACHED | You have used the three successful downloads available for this 24-hour period. Please try again after the limit resets. | The successful-response allowance; another immediate attempt does not reset it. |
RETRY_LATER | All download slots are busy. Please try again shortly. | Processing capacity, not proof that your allowance is exhausted. |
PLATFORM_RATE_LIMIT | Instagram is rate-limiting downloads right now. Please try again shortly. | The handler classified downloader error text as a rate limit. The code alone does not independently verify the upstream cause. |
Three simulated upstream failures did not spend the allowance
On October 8, we made a controlled local downloader exit with “HTTP Error 429: Too Many Requests” three times for the same synthetic test identity. Each call returned 429 with PLATFORM_RATE_LIMIT. Three subsequent successful placeholder responses still returned 200; the next attempt returned DAILY_LIMIT_REACHED before another downloader process started. A private-error control returned 403, not 429.
This measures the local handler with its internal counter enabled. It does not prove which counters an additional production proxy maintains, and the successful responses were 65,536-byte transport placeholders, not fetched or playable Reels.
A busy response happened before a fourth task started
We held three local tasks at explicit file gates using the handler's default concurrency setting. A fourth call returned 429 and RETRY_LATER; its downloader-start marker was absent. After releasing and fully reading the three responses normally, a retry from the fourth test identity returned 200.
No task was cancelled in this experiment. It isolates admission while work is in progress, rather than repeating a tab-close test. The default three-slot result is not a measurement of the live server's configured capacity or a promise about when a real busy response will clear.
Starting a task did not reserve the last allowance
In a separate local sequence, one synthetic identity first received two successful responses. We then started three gated tasks before any of them finished. All three downloader-start markers appeared. Releasing them one at a time produced one 200 response followed by two 429 responses with DAILY_LIMIT_REACHED.
The inspected handler checks the counter again after output preparation; starting work is not a reservation. This explains the measured completion-stage rejection in this local configuration, not an observed production incident. It is a reason to avoid duplicate simultaneous attempts—not a method for obtaining extra downloads.
No measured countdown was returned
Every 429 in these tests had no Retry-After header. The HTTP 429 reference describes that header as optional. Without a returned delay, do not turn “shortly” into a promised number of seconds or assume that a platform limit resets with your own allowance.
Recorded environment and reproduction
October 8, 2026, 11:25:50–11:25:53 (Asia/Shanghai); DESKTOP-OC01O77; Windows 11 Pro 10.0.28000 x64; Node v24.19.0. The handler hash matched the preserved production-source snapshot. We enabled the local internal counter, left the default concurrency value intact, injected downloader failures and released local file gates. We did not inspect runtime environment overrides on the origin or send a production media request.
Read the full grouped inputs and responses or download the self-contained local reproduction. Extract it into an empty directory and run with Node 24.19.0 or a compatible version:
node --import ./scripts/test-typescript-imports.mjs scripts/audit-rate-limit.mjsThe adapter never fetches its Instagram-shaped fixture URLs. The test verifies response codes, complete placeholder byte counts, process-start markers and temporary-file cleanup. These records do not establish a global Instagram threshold or universal retry delay.
For an actual failed attempt
Keep the public Reel URL, exact error text and the time of the attempt. If you use the API, include its HTTP status and error.code; if you use the form, its displayed message is sufficient. If the response is HTML or has no matching message, this table cannot identify its cause. Ask support rather than sending Instagram credentials, changing identities to evade an allowance, or repeatedly launching duplicate requests.
Return to the instagram reel downloader when the relevant limit permits another attempt. For a rejected public link, use the general failure guide; for a response that explicitly says FILE_TOO_LARGE, see the measured file-size check.