Telegram error 400: Bad Request: BUTTON_URL_INVALID
Last verified against Telegram Bot API reference
Bad Request: BUTTON_URL_INVALIDWhat error 400 means
An InlineKeyboardButton with a url field contains something Telegram does not accept as a URL. This is a raw server code surfaced by the Bot API, so it comes back in uppercase without further detail. Telegram validates each button URL at send or edit time; if any one button fails, the entire message is rejected.
Accepted values are ordinary http:// and https:// links, tg:// links, and tg://user?id=<user_id> for mentioning users without usernames (which only works if the user allows it). Anything else, including empty strings, relative paths, unencoded spaces, or schemes like mailto: and javascript:, fails.
A template that renders an empty URL for some records is the most common source of this error appearing 'randomly'.
What it looks like
{"ok":false,"error_code":400,"description":"Bad Request: BUTTON_URL_INVALID"}Why it happens
- An empty or null URL from a template variable that was not set.
- Unencoded characters (spaces, non-ASCII) in a dynamically built link.
- Non-http(s)/tg scheme.
- The URL host is empty, for example
https://followed directly by a path; Telegram also reports this case asBad Request: URL host is empty.
How to fix Telegram error 400
- 1Log the full
reply_markupJSON and check every url field. - 2Validate each URL with a parser before building the keyboard; drop or replace buttons whose URL is empty.
- 3Percent-encode query strings and paths.
- 4Use
callback_dataorweb_appbuttons when the target is not a real URL.
How to stop it recurring
Build keyboards through a helper that refuses to emit a button without a valid absolute URL, and unit-test it with empty and unicode inputs. Keep tracking links short and pre-encoded. Never interpolate user-provided text directly into a URL button.
The other keyboard rejection to know is BUTTON_DATA_INVALID (callback_data over 64 bytes); Telegram validates every button in the markup on send and on edit, so one bad button fails the whole call and the two errors often alternate while a keyboard is being debugged. Deep links you place in buttons can be generated and checked with the Telegram link generator, and the documented button constraints are under keyboard limits.
Official reference: Telegram Bot API reference. See all Telegram error codes or the Telegram limits and quotas.
Related codes
Error 400 - quick answers
What does Telegram error 400 mean?
An InlineKeyboardButton with a url field contains something Telegram does not accept as a URL. This is a raw server code surfaced by the Bot API, so it comes back in uppercase without further detail. Telegram validates each button URL at send or edit time; if any one button fails, the entire message is rejected.
How do I fix Telegram error 400?
1. Log the full reply_markup JSON and check every url field. 2. Validate each URL with a parser before building the keyboard; drop or replace buttons whose URL is empty. 3. Percent-encode query strings and paths. 4. Use callback_data or web_app buttons when the target is not a real URL.
Should I retry after error 400?
No. Retrying the same request produces the same error; the condition has to be fixed first. Treat it as a permanent failure for that message and surface it, rather than looping.
Stop debugging Telegram by hand
Connect the channel through Conferbot: tokens, webhooks and retries are handled, failures show as readable status.