Direct answer · three controlled error-path tests

Why Does an Instagram Reel Download Return 429?

A 429 does not by itself mean your download allowance is used up. In Vidlune's inspected handler, it can mean the allowance is exhausted, all processing slots are busy, or the downloader reported an upstream rate limit. Match the exact message before retrying; there is no single wait time that fits all three.

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.

Inspected handler messages
CodeExact messageWhat to distinguish
DAILY_LIMIT_REACHEDYou 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_LATERAll download slots are busy. Please try again shortly.Processing capacity, not proof that your allowance is exhausted.
PLATFORM_RATE_LIMITInstagram 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.
One HTTP 429 can represent three different inspected handler paths: successful-response allowance, busy processing slots, or a classified upstream rate-limit error.

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.mjs

The 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.