Skip to main content

ResponseWithQrBot — Telegram In-Memory QR Code Generator

Generate sharp 512x512 QR code PNGs from URLs and text strings directly inside Telegram chats via @responseWithQrBot.

ResponseWithQrBot Interface


Technical Architecture: Reverse-Engineering @responseWithQrBot​

I structured @responseWithQrBot around an event-driven pipeline that decouples Telegram Bot API webhook dispatching (responsewithqrbot/handlers.py) from matrix synthesis (responsewithqrbot/core.py). Every QR code is constructed in RAM using python-qrcode and Pillow (PIL) and streamed directly to Telegram via io.BytesIO.

+------------------+ +--------------------------+ +------------------------+
| Telegram Server | -----> | Handler & Auth Layer | -----> | Core QR Engine |
| (Webhook/Update) | | (handlers.py) | | (core.py) |
+------------------+ +--------------------------+ +------------------------+
| |
v v
[Length & Auth Checks] [In-Memory BytesIO PNG]

1. In-Memory QR Matrix Synthesis & Box Resampling​

Standard image resampling filters (such as bilinear or bicubic) introduce anti-aliased gray pixels along module boundaries when scaling QR matrices. In responsewithqrbot/core.py, the rendered matrix is resized to 512x512 pixels using Image.Resampling.BOX to preserve hard pixel edges:

import qrcode
import io
import logging
from settings import settings
from PIL import Image
from typing import Optional

logger = logging.getLogger(__name__)

def generate_qrcode(message: str) -> Optional[io.BytesIO]:
try:
qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_L,
box_size=10,
border=4,
)
qr.add_data(message)
qr.make(fit=True)
img = qr.make_image(fill_color="black", back_color="white")

target_size = (
int(settings.RESPONSEWITHQRBOT_IMAGE_BOX_SIZE),
int(settings.RESPONSEWITHQRBOT_IMAGE_BOX_SIZE),
)
img = img.resize(target_size, Image.Resampling.BOX)

buffer = io.BytesIO()
img.save(buffer, format="PNG")
buffer.seek(0)

return buffer

except Exception as e:
logger.error(f"Error generating QR code: {e}")
return None

2. Payload Validation & Handler Registration​

Before invoking generate_qrcode(), responsewithqrbot/handlers.py validates that incoming text messages do not exceed 256 characters (RESPONSEWITHQRBOT_TEXT_LENGTH), preventing dense, high-version QR matrices that are difficult for phone cameras to scan off a small chat thumbnail:

def parse_update_message(update) -> Optional[str]:
if not update.message.text:
return None
if len(update.message.text) > int(settings.RESPONSEWITHQRBOT_TEXT_LENGTH):
return None
return update.message.text

def register_responsewithqrbot_handlers(dispatcher):
dispatcher.add_handler(CommandHandler('start', handle_start_message))
dispatcher.add_handler(MessageHandler(Filters.text, handle_message))
dispatcher.add_handler(ChatMemberHandler(user_left, ChatMemberHandler.MY_CHAT_MEMBER))

QR Synthesis Specifications​

ParameterConfigured ValueEngineering Rationale
Error CorrectionERROR_CORRECT_L (~7%)Minimizes module grid density for URLs and short text strings
Quiet Zone (border)4 modulesComplies with ISO/IEC 18004 four-module quiet-zone specification
Output Dimensions512 × 512 px (PNG)Prevents Telegram client upscaling blur in chat bubbles
Resampling FilterImage.Resampling.BOXPreserves sharp binary black/white module boundaries
Max Input Length256 charactersKeeps QR version compact and scannable on mobile displays

Stateless Processing & Privacy Guarantees​

  • Zero Disk I/O: QR images are synthesized inside io.BytesIO memory buffers and garbage-collected immediately after Telegram API upload.
  • Instant Browser Alternative: For client-side SVG/Canvas QR generation with custom foreground/background colors, use the browser-based QR Code Generator.

Get notified about updates to this tool

No spam. Just high-quality updates about new features and guides.