Telegram Bot API errors: what 400, 401, 403, 409 and 429 mean
What Telegram Bot API errors mean: 400 Bad Request, 401 Unauthorized, 403 Forbidden, 409 Conflict and 429 Too Many Requests with retry_after. The response fields, the causes and what to do.
When a request to the Telegram Bot API fails, the response is a JSON object with "ok": false, a number in error_code and a text in description. The code usually matches the HTTP status: 400 means the request is wrong, 401 that the token was rejected, 403 that the bot may not do this, 409 that two ways of receiving updates conflict, and 429 that you are sending too many requests. Rely on the description and the optional parameters field: the documentation itself warns that the contents of error_code may change in the future.
What an error looks like
An example response to requests that came too fast:
{"ok":false,"error_code":429,"description":"Too Many Requests: retry after 5","parameters":{"retry_after":5}}
Not every error has parameters. According to the Bot API documentation it is a ResponseParameters object with two optional fields that help you handle the error automatically:
retry_after— the number of seconds to wait before repeating the request after flood control was exceeded;migrate_to_chat_id— the identifier of the supergroup that an ordinary group has been migrated to.
The error texts below come from the documentation and from the open source code of the Bot API server (telegram-bot-api). If you write your bot with a ready-made library, it turns such responses into exceptions: python-telegram-bot has Forbidden, Conflict and RetryAfter, and aiogram has TelegramForbiddenError, TelegramConflictError and TelegramRetryAfter.
Common errors
| Code and description | What it means | What to do |
|---|---|---|
400 Bad Request: chat not found | The bot doesn't know the chat: a typo in chat_id, the person has never written to the bot, or the bot is not in that chat | Check chat_id. A bot can write to a private chat only if the person has started it |
400 Bad Request: message is not modified: ... | You are editing a message and the new text and buttons are exactly the same as the current ones | Don't send an edit when nothing changed |
400 Bad Request: query is too old and response timeout expired or query ID is invalid | A button press is answered too late, or with a wrong identifier | Answer a callback_query with answerCallbackQuery right after you receive it |
400 Bad Request: group chat was upgraded to a supergroup chat | The group became a supergroup and has a new identifier | Take the new identifier from parameters.migrate_to_chat_id and use it |
400 about formatting (can't parse entities and similar) | The text doesn't match the parse_mode: a tag is not closed or special characters are not escaped | Fix or escape the markup; the rules are in the Formatting options section of the documentation |
400 Can't parse ... JSON object | A parameter that must be JSON (such as a keyboard) is written incorrectly | Check the JSON and its encoding |
401 Unauthorized | The token is wrong or has been replaced | Check the token with getMe: how to do it |
403 Forbidden: bot was blocked by the user | The person blocked the bot | Stop writing to them and mark them as unreachable on your side |
403 Forbidden: user is deactivated | The recipient's account is deleted | The same: the message can't be delivered |
403 Forbidden: bot was kicked from the group chat (or supergroup chat, channel chat) | The bot was removed from the group, supergroup or channel | Stop sending messages there |
404 Not Found: method not found | There is no such method: a typo in the name | Check the name against the documentation |
409 Conflict: ... | Two ways of receiving updates are active at once | See the section below |
429 Too Many Requests: retry after N | A request limit was exceeded | Wait N seconds (the retry_after field) and repeat |
500 Internal Server Error | A failure on the server's side | Repeat the request later |
409 Conflict: two ways of receiving updates
Telegram delivers a bot's updates to one receiver only. Error 409 appears in three cases:
Conflict: terminated by other getUpdates request; make sure that only one bot instance is running— two processes are polling the same bot at the same time. Typically that is a copy of the bot on a server and another on your computer, or a restart where the old process hasn't finished yet. Keep one running instance.Conflict: terminated by setWebhook request—setWebhookwas called whilegetUpdateswas polling.Conflict: can't use getUpdates method while webhook is active; use deleteWebhook to delete the webhook first—getUpdateswas called while a webhook is set. Remove it withdeleteWebhook.
Both ways are covered in getUpdates vs webhook.
429 and limits: how to stay under them
According to the bots FAQ, in a single chat you should avoid sending more than one message per second: short bursts are tolerated, but eventually you'll get 429 errors. In a group a bot can't send more than 20 messages a minute, and for bulk notifications not more than about 30 messages a second. For large broadcasts Telegram has paid broadcasts, which you enable in @BotFather: the conditions and the cost are in the Bot API documentation and the FAQ. Without them Telegram advises spreading a broadcast over a longer time, for example 8–12 hours.
What to do on a 429:
- Read
parameters.retry_after. - Wait that many seconds and repeat the request.
- Queue your messages with a pause between them instead of sending everything at once.
How to handle errors
- Always check
ok. If it isfalse, readdescription: the text tells you the cause. - Errors 400, 401 and 403 won't be fixed by repeating: change the request or stop sending. The exception is 429: repeat after the pause.
- Log the
descriptiontogether with the code: the code alone doesn't tell the cause. Don't log the full request URL, because it contains the token. - To see the response code on the command line add
-i:curl -i "https://api.telegram.org/bot<TOKEN>/getMe". How to send a message with a request is shown in the curl guide.
What next
A bot is more reliable when updates arrive without gaps: getUpdates vs webhook. The first message through the API is sendMessage with curl. The token and how to protect it are in a separate guide, and running a bot on a server is in the hosting guide.
Frequently asked questions
What does a Telegram API error mean?
It is a Bot API response with "ok": false: error_code holds a numeric code, description the reason, and sometimes parameters adds a hint such as retry_after. Read the reason in description.
What does error 403 Forbidden: bot was blocked by the user mean?
The person blocked the bot, so you can't write to them. Repeating won't help. They can receive messages again only if they unblock the bot.
How do I fix error 409 Conflict in a Telegram bot?
Run only one instance of the bot. If the error mentions a webhook, remove it with deleteWebhook or stop calling getUpdates.
What should I do on a 429 Too Many Requests error?
Wait the number of seconds given in retry_after and repeat the request. To avoid it, send no more than one message a second to one chat and no more than 20 a minute to a group.
Why does my bot get 401 Unauthorized?
The token is wrong or has been replaced. Check it with getMe and, if needed, get a new one from @BotFather.
What does 400 Bad Request: chat not found mean?
The bot couldn't find the chat: check chat_id, and make sure the person has started the bot and that the bot is a member of the group or channel.


