How to create a game bot and publish your HTML5 games on Telegram

At Ludei we love HTML5 games, that’s what our motto is. That’s us. We have developed a lot of HTML5 games, from showcases to test our platform to fully featured games, with 20M+ downloads. On October 3rd the Telegram team announced its gaming platform, a ready to play, easy to build, social and lightweight solution to provide digital entertainment to Telegram users (like us, the Ludei team). As Telegram’sg announcement tells us: “the underlying technology is HTML5…” , we may have an idea here; grass is green.


After we checked the examples provided and the documentation, we decided that our bot (@ludeiBot) should be capable of serving our games, setting the user’s score and answering inline queries. All this while being a social bot, that is, our bot and our games can and are going to be easily shareable on Telegram itself. Let’s start!

For the bot creation you must contact @BotFather, answer all the questions wisely and you will have your bot available to the world. 

Botfather logo

Botfather logo


When your bot is correctly created you have to register your games on Telegram. A name, a short name, a description and a correctly sized photo is enough for Telegram’s “/newgame” command.

First of all, how are we going to access the Telegram API? A fast Google search returns lots of good and reliable (frequently updated) libraries written in the most modern programming languages. We can choose what to use, there is no problem here. We chose TelegramsBots Java library and the Java programming language.

There are two kinds of Telegram bots depending on how they receive Telegram’s updates. The long polling and webhook bots, for the first prototype, lets keep it simple (KIS(S)). The webhook server requires a server accessible by Telegram while the long-polling bot doesn’t, so we chose the long-polling method for the prototype.


The first command a bot receives from any user is the “/start” command. Is there a better way to start learning the API? From there we move to our own defined commands, “/list”, “/play” and “/random”.

The list command shows our list of games, so we need to store them before answering the command request but, what is the information needed to send a game to a user on Telegram? The only properties needed to send a game are where to send it and what game we are sending, the “chatId” and the game “short name” (the same we registered when creating our game).

With that information stored on the server, we send a list of games using a custom Telegram keyboard to let the user graphically select the desired game.

Telegram's inline keyboard.

Telegram’s inline keyboard.

When a user taps on one of the buttons we defined, the text written on that button is sent back to the server. We process that message and if it follows a concrete arbitrary pattern (“▶️ gameShortName” in our case) we answer the request which executes the”/play” command of our bot.

The “/play” command does the proper game sending process. To do so, we just call Telegram’s API indicating the chatId and the game’s shortname. We also send a custom inline keyboard in this response with two buttons. The first button must, as the documentation indicates, always be the play button.

We had some problems sending this button because we were a little confused by the documentation stating that the “CallbackGame” value is just “a placeholder, currently holds no information”. When trying to set the callback game with this empty placeholder the button (as our logic expected) doesn’t do anything at all.

After reading our Telegram API library source code, we discovered that a proper game callback does contain some values and after setting up a JSON with a unique field “game_short_name” the button works. Please, check the following code snippet:

The “play with friends” button just shares a URL the way the API shares any other URL:

The last command is “/random”, that just selects a random game and sends it back to the channel it was requested from. Internally, it calls the “/play” command again with the game shortname parameter filled (yay, code reuse!).

There is also another topic: the inline queries. Just name our bot @ludeiBot and after writing this, hit space and start writing anything. If one of our games contains the string you have introduced then that game will appear immediately so you can tap and start playing it.

This can be done thanks to Telegram’s inline mode. Each time a user enters a new character, Telegram sends us a new inline query. We get the query text and look for a game containing that text, we collect all the matching games and we send them back before the user can even notice what is happening.

Wait; a request each time a user changes a character, how many requests are we going to process? Can we answer all those requests fast enough for a nice user experience? We use Amazon’s Lambda for other internal services and we have some experience with it, could our bot be hosted in this extremely useful service?

Again, after a fast search we found lots of tutorials helping us with this concrete need , we just need to set Telegram’s webhook location to an Amazon API Gateway endpoint that launches a Lambda function calling our bot with the received update from Telegram.

Just one Amazon Lambda function is enough to receive all the messages from Telegram, process them and answer all the requests. And all this is done in less than 70 ms without spending too much time on code optimization (this could surely be faster) and without losing time and resources dealing with lateral escalation.


Another message that must be processed is the callbackQuery that is being produced when the user taps the “play solo” button of our game message. When the user taps the button, we receive a callbackQuery from the Telegram API containing the tapped game shortName parameter indicating which game the user has selected as well as other parameters.

In order to let the user play, we must then answer this callback with the game’s URL and then Telegram will redirect the user to the game’s site and display it in a webview-like environment.

The last requirement is the score sharing functionality. In order to send a score to Telegram’s API, we have to receive the userId of the player who is scoring, and either both the chatId and the messageId from the chat the game is being played on or only the inlineMessageId from which the game has been launched from.

All this parameters are received in the callbackQuery call after the user taps the “play solo” button. Coincidence?, Sherlock doesn’t think that. When answering the callbackQuery you can specify a custom game URL, so you can include the needed parameters in the URL as query parameters.

From the server perspective, we should receive a POST request to the Amazon API Gateway endpoint containing the needed parameters (the userId, both the chatId and the messageId or the inlineId only).

With this information all we need to do is call the setGameScore method on Telegram’s API setting the needed parameters and voilá. The score is shared in the user’s chat room and when the game is shared again in the same chat you can see a beautiful leaderboard instead of the game description.

Ok. Wait, what!? Let’s review how we managed Telegram’s game lifecycle:

  • First of all, a user requests a game through the “/play” command, pressing a button after a “/list” command is issued or through an inline query.
  • When we receive the request, we answer the request with the sendGame function of the API setting our own buttons.
  • When the user taps the “Play solo” button a callbackQuery is received, we must answer this query by sending the URL of our game. It is useful to also send the needed parameters to use the setScore endpoint.
  • When you score in the game a request is received in the server with the needed information to use the setScore function.

Checkout our published games here:

Jumping submarine

Angry piano