Los widgets en los mensajes —bloques interactivos de HTML, CSS y JavaScript directamente en el chat— han llegado a las versiones beta de Telegram para Android e iOS. El 25 de octubre aparecieron en Android 13.2.0 (7254) e iOS 13.2 (35726), y en Android un widget casero ya ejecuta JavaScript. La build de Android 13.2.0 (7260) del 27 de octubre muestra cómo funciona: sin un motor de navegador, utilizando su propio intérprete con una cuota de CPU, y con un árbitro independiente que decide si un toque fue genuino. El bot al que el widget envía una solicitud conoce el ID del usuario que ha tocado. En Telegram Desktop y en la Bot API pública, los widgets siguen sin estar disponibles.
La mecánica de las solicitudes al bot en la beta para macOS fue analizada en un artículo del 27 de octubre; aquí presentamos lo que añade la build para Android.
Dónde están disponibles los widgets
| Cliente | Build | Lo que se ve |
|---|---|---|
| macOS, beta | 13.1.0 | Sandbox, solicitudes al bot, páginas de prueba — desde mediados de octubre |
| Android, beta | 13.2.0 (7254, 7260) | Esquema, sandbox, textos de interfaz; los widgets funcionan |
| iOS, beta | 13.2 (35726) | Widgets en mensajes y herramientas para su verificación |
| Telegram Desktop | 7.3.3 | No: ni en el código ni en el esquema de la capa 232 |
| Bot API | 10.3 | No |
La beta de Android se distribuye a través del canal oficial y mediante un enlace directo desde el sitio web de Telegram. El protocolo del cliente en esta build es la capa 233, una más reciente que la pública.
Cómo se almacena un widget en un mensaje
Un widget es un nuevo tipo de medio, messageMediaWidget. Además del código en sí (payload) y sus dimensiones, contiene dos conjuntos de datos: chat_data —los datos de este mensaje— y public_data con un hash —datos generales del widget que el bot puede modificar después del envío (messages.editMessageWidgetData, updateMessageWidgetData). Los flags can_query y background_query indican si el widget puede escribir al bot con un toque o sin él, respectivamente, e is_copy marca una copia reenviada. Un widget también puede llegar como un resultado inline del bot — botInlineMessageWidget.
Los permisos los establece el remitente. En los mensajes de error de la parte nativa del cliente se mencionan los flags del servidor allow_queries y fwd_allow_queries: sin el primero, el widget no escribe al bot en absoluto; sin el segundo, su copia reenviada permanece en silencio. Una solicitud en segundo plano requiere además background_query y solo se envía mientras el widget está en pantalla.
Qué recibe el bot
Un toque se convierte en un messages.getBotWidgetQueryAnswer con los campos de chat, mensaje y data —hasta 64 bytes. El bot recibe la actualización updateBotWidgetQuery y responde con el método messages.setBotWidgetQueryAnswer con una sola cadena result.
En la actualización para el bot, el campo user_id es obligatorio, sin flag: el bot siempre sabe quién ha tocado. Junto a él llegan chat_type, chat_instance —el mismo identificador de chat anonimizado que en los botones inline normales—, el número de mensaje y widget_id. Para las copias reenviadas y los mensajes inline existen sus propias actualizaciones — updateBotWidgetCopyQuery y updateInlineBotWidgetQuery.
Esto es similar a tocar un botón inline con un callback, solo que el botón lo dibuja un script y los datos los recopila el mismo script.
Cómo se ejecuta el código del widget
En Android no hay ni WebView ni Chromium bajo el widget. El código se ejecuta mediante la librería nativa twidget dentro de la librería principal del cliente —el mismo nombre llevan los tipos Twidget* en la beta para macOS y el repositorio privado conectado a sus fuentes. Los scripts del sandbox se encuentran en el cliente dos veces: como código fuente y como bytecode .qbc, que ejecuta el intérprete JavaScript integrado. La imagen la dibuja su propio renderer directamente en la ventana de Android —no hay maquetación de navegador, sino su análisis: un paquete validator separado verifica el HTML y CSS.
Las limitaciones están codificadas, no en las reglas para desarrolladores:
- CPU — el widget tiene una cuota de tiempo (
cpuQuotaMs), excederla resulta en el error «CPU limit exceeded»; - Temporizadores — el número de temporizadores simultáneos es limitado, el motor rechaza los adicionales;
- Red —
fetch,XMLHttpRequest,WebSocketynavigator.sendBeaconestán silenciados,navigator.onLinesiempre es falso,userAgentesTelegramWidget/1.0; - Almacenamiento — cada widget comienza con un almacenamiento vacío;
- Salidas externas —
openLinksolo acepta direcciones https de hasta 256 caracteres y pregunta: «This widget wants to open:»,copyText— hasta 256 caracteres; - Puente al cliente — después del inicio, las funciones de servicio
__host,__hostOpsy las adyacentes se eliminan del objeto global, y el código del widget no puede acceder a ellas.
El cliente compara los archivos del sandbox con las sumas de verificación de manifest.txt; una discrepancia genera un error separado «Bundle checksum mismatch».
Cómo el cliente distingue un toque de una imitación
Una solicitud al bot sin permiso de segundo plano solo se envía desde el manejador de un toque —«una llamada por cada toque en un widget visible», como se indica en el mensaje de error. Quien decide si hubo un toque no es el script, sino un árbitro de toques nativo: las funciones arbiterDown, arbiterMove, arbiterUp y arbiterHoldDeadline reciben las coordenadas del dedo y el tiempo de retención. Por diseño, un clic sintético desde JavaScript, un temporizador o un arrastre no enviarán una solicitud.
En la beta también hay herramientas para verificar este límite: la pantalla de conformidad (WidgetConformanceActivity) y la ejecución de un conjunto de ataques (attackScan, WidgetAttacks). El conjunto de páginas de prueba de ataques para macOS —28 páginas que intentan enviar un mensaje sin un toque o redirigir a un enlace— se encuentra en el código abierto del cliente.
Qué ve el usuario
Los textos de la interfaz ya están en el diccionario de cadenas del cliente en inglés: «Loading widget…», «Widget failed to load», «Widget stopped», «Preview of the widget» y la advertencia «This widget can send data to its bot's server when you tap it.»
No hay un interruptor separado en la configuración de la beta para deshabilitar los widgets —los testers han señalado esto. No todos pueden enviar widgets todavía, y la Bot API no tiene métodos para ellos.




