# Telegram Bot API errors: what 400, 401, 403, 409 and 429 mean

How an error response is built, the codes 400, 401, 403, 409 and 429 explained, and what to do about each.

https://shiba-bank.com/en/guides/bot-api-errors

Updated 2026-10-02 · 7 min read

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](https://core.telegram.org/bots/api) 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](https://github.com/tdlib/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](https://shiba-bank.com/en/guides/bot-token) |
| 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` — `setWebhook` was called while `getUpdates` was polling.
- `Conflict: can't use getUpdates method while webhook is active; use deleteWebhook to delete the webhook first` — `getUpdates` was called while a webhook is set. Remove it with `deleteWebhook`.

Both ways are covered in [getUpdates vs webhook](https://shiba-bank.com/en/guides/bot-api-updates).

## 429 and limits: how to stay under them

According to the [bots FAQ](https://core.telegram.org/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](https://core.telegram.org/bots/api) 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:

1. Read `parameters.retry_after`.
2. Wait that many seconds and repeat the request.
3. Queue your messages with a pause between them instead of sending everything at once.

## How to handle errors

- Always check `ok`. If it is `false`, read `description`: 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 `description` together 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](https://shiba-bank.com/en/guides/bot-api-curl).

## What next

A bot is more reliable when updates arrive without gaps: [getUpdates vs webhook](https://shiba-bank.com/en/guides/bot-api-updates). The first message through the API is [sendMessage with curl](https://shiba-bank.com/en/guides/bot-api-curl). The token and how to protect it are in [a separate guide](https://shiba-bank.com/en/guides/bot-token), and running a bot on a server is in the [hosting guide](https://shiba-bank.com/en/guides/bot-hosting).

## 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](https://t.me/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.
