Telegram getFile: Recover Expired Download Links Safely
If a Telegram bot’s file download link expires, call getFile again with the file’s file_id and use the returned file_path. Telegram guarantees the prepared download link for at least one hour, not forever. Do not pass file_unique_id as the download identifier. This recovery applies to the official Bot API; a temporary attachment URL received through a unified webhook has a different contract.
Key takeaways
- Receiving a media message does not mean your application has stored its bytes.
- Keep the file identifier and message context; treat a download URL as a temporary locator.
- Refresh an expired Bot API link through
getFile, rather than retrying the same URL indefinitely. - Do not apply Telegram’s link lifetime or refresh method to UnifyPort attachment URLs.
What getFile returns—and what to keep
The Telegram Bot API reference defines getFile as preparation for downloading a file. It returns a File object. The same reference distinguishes the identifiers:
| Value | Documented purpose | Recommended application use |
|---|---|---|
file_id | Download or reuse a file | Retain with the receiving bot’s identity for later getFile calls |
file_unique_id | Identify a file across time and different bots; cannot download or reuse it | Optional correlation, never a substitute download credential |
file_path | Path used for downloading the prepared file | Use the current response rather than treating an old path as permanent |
file_name, mime_type | Optional sender-supplied document metadata | Preserve from the incoming message where present; validate before use |
Store the originating chat and message identifiers as well. File identity is not conversation authorization: identical media appearing in another chat must not automatically grant that chat access to your stored copy.
These are Bot API fields, not a proposed extension to UnifyPort’s event schema. If you have not chosen an integration model, first read Bot API webhook vs unified inbound webhook.
Diagnose a failed Telegram file download
Use the actual failing stage, not the fact that the inbox displays a thumbnail, to choose recovery.
| Observation | Check next | Recovery boundary |
|---|---|---|
getFile fails | Correct bot credential, actual file_id, returned error, file size | Repair the request or supported download path before retrying |
| A previously working link stops working | Obtain a fresh getFile result | Retry with the newly prepared location; do not assume every HTTP error proves expiry |
| Download times out | Network, worker timeout, storage availability | Use bounded retries; resolve a fresh location if expiry is suspected |
| Download succeeds but parsing fails | Actual bytes and parser support | Refreshing a link does not repair unsupported or invalid content |
| The webhook exists but no owned file exists | Durable media job and worker result | Event acceptance and file persistence are separate milestones |
Telegram currently documents a 20 MB download limit for its hosted Bot API in both the API reference and Bots FAQ. Do not confuse that with upload limits or with every Telegram client capability. The API reference separately documents downloading without that size limit when operating a local Bot API server; that is an infrastructure choice, not a parameter that makes the hosted endpoint accept a larger file.
The one-hour promise is a minimum validity guarantee, not an instruction to wait an hour or a promise that every link fails at exactly that point. A fresh getFile call is the documented way to obtain another link after expiry.
Put file persistence behind durable intake
The following is recommended application architecture, not a Telegram delivery guarantee:
- Persist the received update and enough file metadata to create a download job. Make the job durable before acknowledging intake.
- Let a worker resolve the download location just before fetching, instead of filling a long queue with aging URLs.
- Stream into private temporary storage with your own byte and time limits. Treat sender-provided filenames and MIME types as untrusted metadata.
- Publish an owned storage reference only after the download and your content checks finish. Keep incomplete files out of the support interface and AI processing.
- On failure, retain a redacted reason and a bounded retry decision. If recovery is unavailable, show an attachment-unavailable state rather than claiming the message was never received.
Use an application-controlled filename or object key, not a user-supplied path. Restrict worker network destinations, avoid forwarding service credentials to arbitrary hosts, and keep credentials and signed URLs out of general logs. These are design recommendations; a verified event does not establish that an attached document is safe to open.
Test a delayed job, an expired locator, an oversized file, a missing optional filename, and a worker crash during storage. The acceptance criterion is not merely “HTTP request succeeded”: the correct authorized conversation must receive either a usable owned copy or an explicit failure state. These are proposed tests, not reported results.
UnifyPort media uses a different recovery contract
UnifyPort’s unofficial interface delivers normalized message.received events for connected messaging accounts. The standard event reference documents data.message.attachments[] and temporary signed OSS URLs. The media mapping guide explains the attachment fields; this article addresses what happens after a download job is created.
For that path:
- Verify and durably accept the event according to the webhook delivery reference, then process available attachment URLs promptly under your retention policy.
- Handle missing URLs explicitly. The documented oversized-file representation uses
attachments[].metadata.is_big_filewithurlomitted; do not invent a download URL from a message ID. - Do not assume a normalized attachment exposes a Bot API
file_id, or send its URL togetFile. - Do not copy the Bot API’s one-hour guarantee or 20 MB limit into your UnifyPort worker configuration as product facts.
The public UnifyPort reference does not document an attachment-URL refresh endpoint. It also states that there is no REST message-history read API or guaranteed replay of missed payloads. If a URL is no longer usable and you have no owned copy, do not promise recovery by reconnecting the account. Record the limitation and arrange an authorized resend or manual follow-up when necessary.
FAQ
Can file_unique_id be used with getFile?
No. Telegram explicitly says it cannot be used to download or reuse a file. Keep file_id for the download workflow.
Does a Telegram download link expire after exactly one hour?
Not necessarily. Telegram guarantees validity for at least one hour. When it expires, request another link through getFile.
Should the browser or an AI service receive the original download URL?
Prefer a backend download and an application-authorized storage reference. Do not expose credentials or broadly distribute temporary signed URLs merely to display an attachment.
Can getFile renew a UnifyPort attachment URL?
No such interoperability is documented. Use each interface’s own contract and do not invent a refresh operation.
Next step and sources
Review the standard webhook event contract and add explicit file-persistence success and failure states to your media worker before connecting downstream automation.
Sources checked on 2026-09-24:
Turn messaging integration into a stable product pipeline.
Start by sending through one API, then bring every inbound message back into your business system with standard events.