Telegram Bot API przez proxy: konfiguracja długiego pollingu, webhooków i obsługi błędu 429
Spis treści
- Wprowadzenie: co zyskasz dzięki temu przewodnikowi
- Przygotowanie wstępne: narzędzia i dostępy
- Podstawowe pojęcia: jak zbudowane jest telegram bot api
- Krok 1: tworzymy bota i pobieramy token
- Krok 2: podłączamy proxy i sprawdzamy dostęp do api
- Krok 3: uruchamiamy długi polling przez proxy
- Krok 4: konfigurujemy webhook z https i tokenem sekretnym
- Krok 5: obsługujemy błąd 429 i czynimy żądania odpornymi
- Krok 6: zaawansowane ustawienia dla obciążonych projektów
- Sprawdzenie rezultatu: lista kontrolna gotowego rozwiązania
- Typowe błędy i ich rozwiązania
- Faq: częste pytania o konfigurację
- Zakończenie
Wprowadzenie: co zyskasz dzięki temu przewodnikowi
Jeśli choć raz uruchamiałeś bota w Telegramie, znasz tę nieprzyjemną rzecz. Sam bot powstaje w jeden wieczór, ale jego stabilne działanie staje się osobnym projektem. Wiadomości przychodzą z opóźnieniem, aktualizacje giną, serwer nagle dostaje błąd 429, a webhook po prostu przestaje być wywoływany bez wyjaśnienia. Dodaj do tego proxy, przez które muszą przechodzić wszystkie żądania, a liczba punktów awarii podwaja się.
Ten przewodnik krok po kroku rozwiązuje właśnie te problemy. Nauczysz się pracować z Telegram Bot API przez serwer proxy tak, aby bot nie padał, nie gubił wiadomości i prawidłowo reagował na limity. Nie będziemy omawiać protokołu MTProto ani budować systemu monitoringu proxy. Nasz temat jest węższy i bardziej praktyczny: żądania HTTP do api.telegram.org przez proxy, dwa sposoby odbierania aktualizacji i właściwa reakcja na ograniczenia.
Co ostatecznie zyskasz
- Działającego bota, który wysyła żądania do Telegram Bot API przez Twoje proxy (HTTP lub SOCKS5).
- Skonfigurowany długi polling, który nie zrywa się na timeoutach i nie duplikuje wiadomości.
- Webhook z HTTPS i tokenem sekretnym, odbierający aktualizacje na Twoim serwerze.
- Gotową otoczkę dla żądań, która sama czeka odpowiedni czas przy błędzie 429 i powtarza wysyłkę.
- Zrozumienie, który tryb wybrać dla swojego projektu: polling czy webhook.
Dla kogo jest ten przewodnik
Dla marketerów i specjalistów od arbitrażu, którzy tworzą boty do rozsyłania wiadomości, powiadomień o leadach i statystyk kampanii. Dla programistów, którym potrzebny jest stały i przewidywalny wychodzący adres IP dla żądań serwerowych. Dla właścicieli firm, których boty obsługują klientów i nie mogą milczeć przez godzinę. Jeśli pracujesz z mobilnymi proxy i chcesz przepuścić przez nie ruch bota, trafiłeś we właściwe miejsce.
Co warto wiedzieć wcześniej
Wyjaśniamy każdy krok od zera, ale kilka podstawowych umiejętności znacznie ułatwi życie. Przyda się umiejętność otwarcia terminala lub wiersza poleceń, kopiowania poleceń i uruchamiania skryptów w Pythonie. Znajomość tego, czym jest żądanie HTTP i JSON, jest wskazana, ale przypomnimy to prostymi słowami. Tematy zaawansowane zostały wydzielone do osobnej sekcji, początkujący mogą ją pominąć bez utraty rezultatu.
Ile czasu to zajmie
Przygotowanie i utworzenie bota zajmie około 20 minut. Konfiguracja proxy i pierwsze udane żądanie kolejne 20-30 minut. Długi polling uruchomisz w pół godziny. Webhook wymagać będzie 40-60 minut, ponieważ potrzebny jest certyfikat HTTPS. Obsługa błędu 429 doda jeszcze 20 minut. Razem od dwóch do trzech godzin spokojnej pracy z weryfikacją na każdym etapie.
Przygotowanie wstępne: narzędzia i dostępy
Zanim napiszesz pierwszą linię kodu, zbierzmy wszystko, co potrzebne. Dzięki temu nie będziesz przerywać pracy w połowie kroku i szukać, skąd wziąć hasło do proxy albo jak zainstalować bibliotekę.
Niezbędne narzędzia i dostępy
- Konto Telegram z przypisanym numerem. Z niego utworzysz bota przez oficjalnego bota BotFather.
- Dostęp do proxy: adres serwera, port, login i hasło. W panelu klienta mobileproxy.space te dane są widoczne w karcie zakupionego proxy. Zwykle dostępne są dwa porty: jeden do połączenia HTTP, drugi do SOCKS5. Zapisz oba.
- Komputer lub serwer z zainstalowanym Pythonem 3.10 lub nowszym. Do webhooka potrzebny będzie serwer z publicznym adresem IP i domeną, na domowym komputerze webhook nie zadziała.
- Narzędzie curl. W Windows 10 i 11, macOS oraz Linux jest już wbudowane. Sprawdź poleceniem
curl --version. - Edytor tekstu: VS Code, Notepad++ lub inny, w którym wygodnie pisze się kod.
Wymagania systemowe
Dla pollingu wymagania są niemal żadne: dowolna maszyna z dostępem do internetu, w tym laptop. Bot zużywa kilkadziesiąt megabajtów pamięci. Do webhooka potrzebny jest VPS w minimalnej konfiguracji: 1 rdzeń, 1 GB pamięci RAM, Ubuntu 22.04 lub 24.04. Obowiązkowa jest domena wskazująca na IP tego serwera i otwarty port 443 w zaporze sieciowej.
Co zainstalować
- Otwórz terminal.
- Sprawdź Pythona poleceniem
python3 --version. W Windows polecenie może wyglądać jakpython --version. - Utwórz folder projektu:
mkdir tgbot-proxy, następnie przejdź do niegocd tgbot-proxy. - Utwórz środowisko wirtualne:
python3 -m venv venv. Aktywuj je: na Linux i macOSsource venv/bin/activate, w Windowsvenv\Scripts\activate. - Zainstaluj biblioteki:
pip install requests[socks] flask. Pakiet requests odpowiada za żądania do Telegram Bot API, dodatek socks jest potrzebny do proxy po protokole SOCKS5, a Flask odbierze webhook.
Kopie zapasowe i bezpieczeństwo danych
Token bota traktuj jak hasło do aplikacji bankowej. Ten, kto go zdobędzie, będzie mógł pisać w imieniu bota do Twoich klientów. Utwórz plik .env z tokenem i danymi proxy i nigdy nie wysyłaj go do publicznego repozytorium. Jeśli bot już działa i przenosisz go na proxy, zapisz obecną konfigurację, zrób eksport bazy danych, jeśli ją masz, i zapisz wynik metody getWebhookInfo. Wtedy wycofanie zmian zajmie dwie minuty.
Wskazówka: Załóż osobnego bota testowego do eksperymentów. Wszystkie kroki tego przewodnika najpierw przećwicz na nim, a na bota produkcyjnego przenoś tylko sprawdzoną konfigurację. Dzięki temu nie zepsujesz komunikacji z rzeczywistymi klientami.
Podstawowe pojęcia: jak zbudowane jest Telegram Bot API
Omówmy kluczowe terminy prostymi słowami. Bez nich kolejne kroki będą wyglądać jak magia, a z nimi staną się logiczne i przewidywalne.
Telegram Bot API
To zwykły interfejs HTTP. Twój kod wysyła żądanie na adres postaci https://api.telegram.org/bot<ТОКЕН>/<метод>, a serwer Telegram odpowiada obiektem JSON. Na przykład metoda getMe zwraca informacje o bocie, a sendMessage wysyła tekst na czat. Do pracy nie są potrzebne specjalne biblioteki, wystarczy curl lub requests. Właśnie dlatego Telegram Bot API tak łatwo przepuścić przez proxy: to ten sam ruch, co w przypadku dowolnej strony po HTTPS.
Aktualizacje (updates)
Każde zdarzenie dla bota, czy to wiadomość, naciśnięcie przycisku czy dodanie do grupy, przychodzi jako obiekt update z unikalnym numerem update_id. Numery rosną po kolei. Zadaniem Twojego kodu jest odebranie tych obiektów i ich obsłużenie. Sposobów odbioru są dokładnie dwa i wykluczają się wzajemnie.
Długi polling (long polling)
Twój bot sam pyta Telegram: czy są dla mnie nowe aktualizacje? Robi to metodą getUpdates. Słowo „długi” oznacza, że serwer nie odpowiada natychmiast pustą listą, ale trzyma połączenie otwarte do określonego timeoutu, zwykle 30-60 sekund, i odpowiada od razu, gdy pojawi się zdarzenie. Oszczędza to żądania i daje niemal natychmiastową reakcję. Polling nie wymaga publicznego adresu, działa zza routera i przez dowolne proxy. Idealny na start i dla botów o małym obciążeniu.
Webhook
Podejście odwrotne. Informujesz Telegram o adresie swojego serwera metodą setWebhook, a Telegram sam przysyła każdą aktualizację żądaniem POST na ten adres. Nie musisz nic odpytywać. Wymagania: publiczna domena, certyfikat HTTPS i jeden z portów 443, 80, 88 lub 8443. Webhook lepiej się skaluje i nie zużywa zasobów na oczekiwanie.
Ważne, by zrozumieć: proxy wpływa tylko na wychodzące żądania Twojego bota do Telegramu. Przychodzące żądania webhooka docierają bezpośrednio na Twój serwer i proxy nie bierze w tym udziału. Dlatego wyrażenie „webhook przez proxy” w praktyce oznacza: bot odpowiada i wywołuje metody API przez proxy, a aktualizacje odbiera na swoim publicznym adresie.
Błąd 429 Too Many Requests
Telegram ogranicza częstotliwość żądań. Orientacyjne wartości na 2026 rok: nie więcej niż jedna wiadomość na sekundę do jednego czatu, nie więcej niż 20 wiadomości na minutę do jednej grupy i około 30 wiadomości na sekundę łącznie na bota. Po przekroczeniu serwer zwraca status HTTP 429, a w treści odpowiedzi pole parameters.retry_after z liczbą sekund oczekiwania. Nie można go ignorować: ponowne próby bez przerw wydłużają czas blokady.
Po co w ogóle proxy dla bota
Powody są czysto praktyczne. Po pierwsze, stały i przewidywalny wychodzący adres IP: wygodne, gdy serwerów jest wiele, a zewnętrzny adres potrzebny jest jeden. Po drugie, rozdzielenie ruchu według projektów: każdy klient lub każda kampania ma swój kanał. Po trzecie, polityki korporacyjne, gdy wszystkie połączenia zewnętrzne muszą przechodzić przez bramę. Mobilne proxy są tu cenne ze względu na stabilność i możliwość zarządzania zmianą IP według harmonogramu lub przez link.
Krok 1: Tworzymy bota i pobieramy token
Cel etapu: uzyskać token dostępu do Telegram Bot API i upewnić się, że bot istnieje.
- Otwórz Telegram na telefonie lub komputerze.
- W polu wyszukiwania wpisz BotFather. Wybierz bota z niebieskim znacznikiem weryfikacji, fałszywe go nie mają.
- Naciśnij przycisk Start lub wyślij polecenie
/start. Zobaczysz listę dostępnych poleceń. - Wyślij polecenie
/newbot. - BotFather poprosi o nazwę bota. Wpisz nazwę wyświetlaną, na przykład Proxy Test Bot. Może zawierać spacje i polskie znaki.
- Następnie poprosi o username. Musi być unikalny, łaciński i kończyć się na
bot, na przykładproxy_test_2026_bot. Jeśli nazwa jest zajęta, BotFather o tym poinformuje, wymyśl inną. - W odpowiedzi przyjdzie wiadomość z gratulacjami i ciągiem postaci
123456789:AAExampleTokenLettersAndDigits. To jest token. Skopiuj go w całości, łącznie z cyframi przed dwukropkiem. - Utwórz w folderze projektu plik
.envi wpisz do niego wierszBOT_TOKEN=ваш_токен.
Uwaga: Nigdy nie publikuj tokenu na czatach, zrzutach ekranu ani w otwartych repozytoriach. Jeśli token wyciekł, natychmiast wyślij BotFather polecenie /revoke, wybierz bota i uzyskaj nowy token. Stary przestanie działać od razu.
Pierwsze żądanie bez proxy
Zanim skomplikujemy schemat, sprawdźmy, czy token działa, zwykłym żądaniem z Twojej maszyny. Wykonaj w terminalu, podstawiając swój token:
curl https://api.telegram.org/bot123456789:AAExampleToken/getMeOczekiwana odpowiedź: JSON zaczynający się od {"ok":true,"result":{"id":123456789,"is_bot":true,.... W środku zobaczysz username bota, który właśnie wymyśliłeś.
Sprawdzenie: W odpowiedzi jest "ok":true i prawidłowy username. Jeśli zamiast tego przyszło "error_code":401, token został skopiowany z błędem, sprawdź, czy nie zginęły znaki na brzegach.
Możliwe problemy
- Username zajęty. Dodaj cyfry lub skrót projektu, ważne, by zachować końcówkę bot.
- BotFather nie odpowiada. Upewnij się, że otworzyłeś bota ze znacznikiem weryfikacji, a nie imiennika.
- Błąd 404 Not Found. W adresie brakuje słowa bot przed tokenem. Format jest ściśle
/bot<ТОКЕН>/метод.
Krok 2: Podłączamy proxy i sprawdzamy dostęp do API
Cel etapu: sprawić, by żądania do Telegram Bot API przechodziły przez Twoje proxy, i potwierdzić to faktycznie, a nie na słowo.
Rozumiemy format adresu proxy
Proxy opisuje jeden ciąg: протокол://логин:пароль@хост:порт. Weź dane z panelu klienta. Załóżmy, że przydzielono Ci host proxy-host, port HTTP 8080, port SOCKS5 1080, login user i hasło pass. Wtedy ciągi będą takie:
- Proxy HTTP:
http://user:pass@proxy-host:8080 - Proxy SOCKS5:
socks5h://user:pass@proxy-host:1080
Zwróć uwagę na literę h w socks5h. Oznacza, że nazwa domenowa api.telegram.org będzie rozwiązywana po stronie proxy, a nie na Twojej maszynie. To właściwy wariant dla mobilnych proxy: zapytania DNS i ruch idą jedną trasą. Bez litery h przy problemach z lokalnym DNS żądania będą padać, choć proxy jest sprawne.
Jeśli w haśle są znaki @, : lub /, trzeba je zakodować: @ zamienia się na %40, dwukropek na %3A, ukośnik na %2F. Inaczej ciąg zostanie źle zinterpretowany.
Sprawdzenie przez curl
- Najpierw sprawdź, jaki adres IP widzą zewnętrzne serwisy przez Twoje proxy. Wykonaj:
curl -x http://user:pass@proxy-host:8080 https://api.ipify.org. W odpowiedzi przyjdzie adres IP. Powinien różnić się od Twojego domowego lub serwerowego adresu. - Teraz to samo żądanie do Telegram Bot API:
curl -x http://user:pass@proxy-host:8080 https://api.telegram.org/bot123456789:AAExampleToken/getMe. - Dla SOCKS5 zmień parametr:
curl -x socks5h://user:pass@proxy-host:1080 https://api.telegram.org/bot123456789:AAExampleToken/getMe. - Zmierze czas odpowiedzi: dodaj na końcu polecenia
-w " czas: %{time_total}". Wartość do 1-2 sekund dla mobilnego proxy jest normalna.
Sprawdzenie: Oba żądania zwróciły "ok":true, a IP z pierwszego polecenia różni się od Twojego własnego. Oznacza to, że trasa przez proxy działa i Telegram Bot API odpowiada na niej.
Konfigurujemy proxy w Pythonie
Utwórz plik config.py o następującej zawartości, zastępując wartości swoimi:
import os
TOKEN = os.getenv('BOT_TOKEN', '123456789:AAExampleTokenReplaceMe')
PROXY = os.getenv('BOT_PROXY', 'http://user:pass@proxy-host:8080')
PROXIES = {'http': PROXY, 'https': PROXY}
BASE = f'https://api.telegram.org/bot{TOKEN}'Klucz https w słowniku jest obowiązkowy, ponieważ Telegram Bot API działa tylko po HTTPS. Częsty błąd początkujących to podanie tylko http i zdziwienie, dlaczego ruch idzie bezpośrednio.
Teraz skrypt testowy check.py:
import requests
from config import PROXIES, BASE
ip = requests.get('https://api.ipify.org', proxies=PROXIES, timeout=15).text
print('Wychodzący IP:', ip)
me = requests.get(f'{BASE}/getMe', proxies=PROXIES, timeout=15).json()
print('Bot:', me['result']['username'])Uruchom: python check.py. Na ekranie pojawi się IP proxy i username bota.
Wskazówka: Jeśli nie chcesz zmieniać kodu biblioteki, której już używasz, ustaw zmienną środowiskową HTTPS_PROXY=http://user:pass@proxy-host:8080. Biblioteka requests i większość klientów HTTP podchwytują ją automatycznie. To wygodny sposób przeniesienia istniejącego bota na proxy bez zmian w kodzie.
Konfiguracja w popularnych frameworkach
- aiogram 3.x: utwórz sesję
AiohttpSession(proxy='http://user:pass@proxy-host:8080')i przekaż ją przy tworzeniu obiektuBot(token=TOKEN, session=session). Dla SOCKS5 potrzebny będzie pakiet aiohttp-socks. - python-telegram-bot 21.x: użyj
HTTPXRequest(proxy='http://user:pass@proxy-host:8080')i przekaż go doApplicationBuilder().token(TOKEN).request(request). - Node.js: pakiet https-proxy-agent lub socks-proxy-agent tworzy agenta, który przekazuje się w opcjach klienta HTTP lub w konstruktorze biblioteki bota.
Możliwe problemy
- 407 Proxy Authentication Required. Błędny login lub hasło albo niezakodowane znaki specjalne. Sprawdź dane w panelu.
- Connection refused. Port podany nieprawidłowo lub pomylone porty HTTP i SOCKS5. Spróbuj drugiego portu.
- Żądanie idzie bezpośrednio. W słowniku nie ma klucza https lub zmienna środowiskowa została ustawiona w innym oknie terminala.
- Błąd SSL. Nie wyłączaj weryfikacji certyfikatu. Zaktualizuj pakiet certifi poleceniem
pip install -U certifii sprawdź czas systemowy.
Krok 3: Uruchamiamy długi polling przez proxy
Cel etapu: uzyskać działającego bota, który przez proxy pobiera aktualizacje metodą getUpdates i odpowiada na wiadomości, nie gubiąc ich i nie duplikując.
Jak prawidłowo budować pętlę pollingu
Logika jest prosta, ale ważne są szczegóły. Wywołujesz getUpdates z parametrem offset równym ostatniemu obsłużonemu update_id plus jeden. W ten sposób Telegram rozumie, że poprzednie aktualizacje zostały odebrane, i usuwa je po swojej stronie. Jeśli zapomnisz o offset, ta sama wiadomość będzie przychodzić w kółko, a bot zacznie odpowiadać kilka razy.
Parametr timeout określa, ile sekund serwer trzyma połączenie w oczekiwaniu na zdarzenia. Tu zaczyna się specyfika proxy. Każde proxy ma własny timeout nieaktywnego połączenia, w mobilnych proxy często około 60-120 sekund. Jeśli timeout pollingu jest większy, proxy przerwie połączenie wcześniej, niż odpowie Telegram, i zamiast aktualizacji dostaniesz błąd. Bezpieczna wartość timeout=50 przy timeoutcie klienta HTTP 60 sekund. Timeout klienta zawsze powinien być większy niż timeout pollingu, inaczej klient odłączy się pierwszy.
Piszemy bota
- Utwórz plik
polling.py. - Skopiuj poniższy kod.
- Uruchom go poleceniem
python polling.py. - Napisz do bota dowolną wiadomość w Telegramie.
import time, requests
from config import PROXIES, BASE
offset = 0
print('Polling uruchomiony przez proxy')
while True:
try:
r = requests.get(f'{BASE}/getUpdates', params={'offset': offset, 'timeout': 50}, proxies=PROXIES, timeout=60)
data = r.json()
except requests.RequestException as e:
print('Błąd sieci:', e)
time.sleep(3)
continue
if not data.get('ok'):
print('Błąd API:', data)
time.sleep(3)
continue
for upd in data['result']:
offset = upd['update_id'] + 1
msg = upd.get('message')
if msg and 'text' in msg:
requests.post(f'{BASE}/sendMessage', json={'chat_id': msg['chat']['id'], 'text': 'Przyjąłem: ' + msg['text']}, proxies=PROXIES, timeout=15)Przeanalizujmy, co się tu dzieje. Zewnętrzna pętla nigdy nie kończy się sama. Blok try przechwytuje błędy sieciowe: zerwanie proxy, timeout, zmianę IP. Przy błędzie skrypt czeka trzy sekundy i próbuje ponownie, zamiast padać. Sprawdzenie data.get('ok') łapie błędy na poziomie API. Wewnętrzna pętla obsługuje każdą aktualizację i od razu przesuwa offset.
Sprawdzenie: W konsoli pojawił się wiersz o uruchomieniu, a po wysłaniu wiadomości bot odpowiedział „Przyjąłem: Twój tekst”. Wyślij trzy wiadomości pod rząd, bot powinien odpowiedzieć dokładnie na każdą po jednym razie. Zatrzymaj skrypt klawiszami Ctrl+C, wyślij wiadomość, uruchom ponownie: bot odpowie na pominiętą wiadomość, ponieważ Telegram przechowuje nieobsłużone aktualizacje do 24 godzin.
Specyfika mobilnych proxy przy pollingu
Mobilne proxy potrafią zmieniać adres IP: według timera lub przez specjalny link z panelu. W momencie zmiany IP otwarte połączenie pollingu zostaje zerwane. To nie błąd Twojego kodu, to normalne zachowanie sieci. Nasza pętla jest już na to przygotowana: przechwyci wyjątek, poczeka i kontynuuje od tego samego offset. Żadna aktualizacja nie zginie.
Niemniej częsta rotacja tworzy dodatkowy szum w logach i mikrozacięcia. Zalecenie: dla bota na pollingu ustaw w panelu interwał rotacji od 10 minut w górę albo wyłącz automatyczną zmianę i zmieniaj IP przez link tylko wtedy, gdy naprawdę tego potrzebujesz. Bot to nie scraper, nie potrzebuje świeżego adresu co minutę.
Wskazówka: Dodaj do logu czas i update_id każdej aktualizacji. Gdy za tydzień ktoś powie, że bot nie odpowiedział, w minutę znajdziesz, czy wiadomość dotarła do Twojego kodu, czy problem był po stronie sieci.
Możliwe problemy
- Błąd 409 Conflict. Najczęstszy. Dla bota ustawiony jest webhook, a polling i webhook jednocześnie działać nie mogą. Wykonaj
curl -x twoje_proxy https://api.telegram.org/botТОКЕН/deleteWebhooki uruchom skrypt ponownie. Druga przyczyna: uruchomione są dwie kopie skryptu, zamknij zbędną. - Bot odpowiada na każdą wiadomość dwa razy. Offset nie przesuwa się lub uruchomione są dwie kopie bota.
- Ciągłe Read timed out. Timeout pollingu jest większy niż timeout proxy. Zmniejsz timeout do 30-40 sekund.
- Opóźnienie odpowiedzi 5-10 sekund. Sprawdź czas odpowiedzi proxy przez curl. Jeśli sam kanał jest wolny, zmień punkt wyjścia lub taryfę.
Krok 4: Konfigurujemy webhook z HTTPS i tokenem sekretnym
Cel etapu: Telegram sam przysyła aktualizacje na Twój serwer, a bot odpowiada przez proxy. Ten krok wymaga VPS z domeną, więc jeśli na razie masz tylko polling i Ci wystarcza, możesz przejść do kroku 5 i wrócić tu później.
Przygotowanie serwera i domeny
- Wynajmij VPS z Ubuntu. Zapisz jego publiczny IP.
- W panelu zarządzania domeną utwórz rekord A, na przykład
bot.example.com, wskazujący na IP serwera. Poczekaj na aktualizację DNS, zwykle 5-30 minut. Sprawdź poleceniemnslookup bot.example.com. - Połącz się z serwerem przez SSH i zaktualizuj pakiety:
sudo apt update. - Zainstaluj nginx i certbot:
sudo apt install nginx certbot python3-certbot-nginx. - Otwórz porty 80 i 443:
sudo ufw allow 80,sudo ufw allow 443. - Uzyskaj darmowy certyfikat:
sudo certbot --nginx -d bot.example.com. Postępuj zgodnie z podpowiedziami, podaj email, zaakceptuj warunki. Po minucie certyfikat będzie wydany.
Telegram przyjmuje webhooki tylko po HTTPS z ważnym certyfikatem od zaufanego centrum. Certyfikat od certbot spełnia ten wymóg. Samopodpisany certyfikat też jest możliwy, ale wtedy jego część publiczną trzeba wgrać parametrem certificate w setWebhook, co dodaje kłopotów. Dla początkujących certbot jest prostszy.
Konfigurujemy nginx jako punkt wejścia
Nginx będzie odbierać żądania HTTPS od Telegramu i przekazywać je do Twojej aplikacji Flask, która nasłuchuje na lokalnym porcie 8080. Otwórz konfigurację strony utworzoną przez certbot poleceniem sudo nano /etc/nginx/sites-available/default i dodaj wewnątrz bloku server z portem 443 taką lokalizację:
location /tg/webhook {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_read_timeout 30s;
}Zapisz plik, sprawdź składnię sudo nginx -t i przeładuj sudo systemctl reload nginx.
Wskazówka: Zrób ścieżkę webhooka nieoczywistą, na przykład /tg/webhook/k8s7d2f. To nie zastępuje tokenu sekretnego, ale jest dodatkową warstwą: przypadkowe skanery nie znajdą Twojego punktu wejścia.
Piszemy handler webhooka
Utwórz na serwerze plik webhook.py. Odbiera on POST od Telegramu, sprawdza nagłówek sekretny i odpowiada użytkownikowi przez proxy. Funkcję call napiszemy w następnym kroku, na razie użyj zwykłego requests.post z proxies.
import requests
from flask import Flask, request, abort
from config import PROXIES, BASE
app = Flask(__name__)
SECRET = 'MySecret123'
@app.post('/tg/webhook')
def webhook():
if request.headers.get('X-Telegram-Bot-Api-Secret-Token') != SECRET:
abort(403)
update = request.get_json(silent=True) or {}
msg = update.get('message')
if msg and 'text' in msg:
requests.post(f'{BASE}/sendMessage', json={'chat_id': msg['chat']['id'], 'text': 'Otrzymałem przez webhook'}, proxies=PROXIES, timeout=15)
return 'ok', 200
if __name__ == '__main__':
app.run(host='127.0.0.1', port=8080)Kluczowy moment: nagłówek X-Telegram-Bot-Api-Secret-Token. Telegram dodaje go do każdego żądania, jeśli podałeś secret_token przy instalacji webhooka. Każde żądanie bez prawidłowej wartości jest odrzucane z kodem 403. Dzięki temu nikt postronny nie może podrzucić botowi fałszywych wiadomości.
Uruchom aplikację: python webhook.py. Do stałej pracy później przygotujesz ją jako usługę systemd, ale do sprawdzenia wystarczy bezpośrednie uruchomienie.
Rejestrujemy webhook przez proxy
Samo wywołanie setWebhook też idzie przez proxy, bo to żądanie wychodzące do Telegram Bot API. Wykonaj na dowolnej maszynie z dostępem do proxy:
curl -x http://user:pass@proxy-host:8080 -F "url=https://bot.example.com/tg/webhook" -F "secret_token=MySecret123" -F "max_connections=40" -F "drop_pending_updates=true" https://api.telegram.org/bot123456789:AAExampleToken/setWebhookPrzeanalizujmy parametry. url — adres Twojego handlera. secret_token — ciąg od 1 do 256 znaków z łacińskich liter, cyfr, myślnika i podkreślenia; musi być zgodny z SECRET w kodzie. max_connections — ile równoczesnych żądań Telegram może otworzyć do Ciebie, od 1 do 100, domyślnie 40. drop_pending_updates — zresetować nagromadzone aktualizacje, aby bot nie wypluł lawiny starych odpowiedzi w momencie przełączania.
Oczekiwana odpowiedź: {"ok":true,"result":true,"description":"Webhook was set"}.
Diagnostyka przez getWebhookInfo
To główne narzędzie debugowania webhooków. Wykonaj:
curl -x http://user:pass@proxy-host:8080 https://api.telegram.org/bot123456789:AAExampleToken/getWebhookInfoW odpowiedzi patrz na pola: url powinien być zgodny z Twoim, pending_update_count pokazuje kolejkę nieobsłużonych aktualizacji, last_error_date i last_error_message pojawiają się, jeśli Telegram nie mógł dostarczyć aktualizacji. Puste pole błędu po wysłaniu testowej wiadomości oznacza pełny sukces.
Sprawdzenie: Napisz do bota. Odpowiedział „Otrzymałem przez webhook”. W getWebhookInfo nie ma last_error_message, a pending_update_count wynosi zero. W logach Flask widać wiersz z POST /tg/webhook i kodem 200.
Uwaga: Handler webhooka musi odpowiadać szybko, w ciągu kilku sekund. Jeśli Twój kod długo myśli, na przykład wykonuje ciężkie zapytanie do bazy lub do zewnętrznego serwisu przez wolne proxy, Telegram uzna dostarczenie za nieudane i powtórzy je. Ciężką pracę przenieś do zadania w tle, a webhookowi zwracaj 200 od razu.
Możliwe problemy
- last_error_message: SSL error. Certyfikat jest nieprawidłowy, wygasł lub został wydany na inną domenę. Sprawdź
sudo certbot certificates. - Connection timed out. Port 443 jest zamknięty w zaporze lub u hostera. Sprawdź
sudo ufw statusi ustawienia w panelu VPS. - Wrong response from the webhook: 403. Token sekretny w kodzie i w setWebhook nie są zgodne. Sprawdź wielkość liter.
- Wrong response from the webhook: 502. Flask nie jest uruchomiony lub nasłuchuje na innym porcie. Sprawdź
ss -tlnp | grep 8080. - Bad webhook: port not allowed. Używaj tylko 443, 80, 88 lub 8443.
Krok 5: Obsługujemy błąd 429 i czynimy żądania odpornymi
Cel etapu: napisać jedną funkcję dla wszystkich wywołań Telegram Bot API, która sama wytrzymuje pauzę przy 429, powtarza żądanie przy awariach sieci i proxy i nigdy nie przewraca bota.
Dlaczego 429 nie można ignorować
Gdy wysyłasz rozsyłkę do tysiąca użytkowników, limit 30 wiadomości na sekundę zostaje osiągnięty natychmiast. Telegram odpowiada 429 i wskazuje retry_after. Jeśli dalej bombardujesz serwer, wiadomości nie pójdą, a czas oczekiwania w kolejnych odpowiedziach wzrośnie. Przy pracy przez proxy jest niuans: limity Telegramu są przypisane do bota, a nie do IP. Zmiana IP przez rotację nie pomoże obejść ograniczenia i nie powinna być do tego używana. Jedyna właściwa droga to respektowanie retry_after i kontrolowanie szybkości wysyłki.
Piszemy uniwersalną otoczkę
Dodaj do pliku config.py lub do osobnego api.py następującą funkcję:
import time, requests
from config import PROXIES, BASE
def call(method, payload, retries=6):
for attempt in range(retries):
try:
r = requests.post(f'{BASE}/{method}', json=payload, proxies=PROXIES, timeout=15)
except requests.RequestException as e:
print('Sieć lub proxy:', e)
time.sleep(min(2 ** attempt, 30))
continue
if r.status_code == 429:
wait = r.json().get('parameters', {}).get('retry_after', 1)
print('429 Too Many Requests, czekamy', wait, 'sek'
time.sleep(wait + 0.5)
continue
if 500 <= r.status_code < 600:
print('Błąd serwera Telegram', r.status_code)
time.sleep(min(2 ** attempt, 30))
continue
data = r.json()
if not data.get('ok'):
print('Błąd API:', data.get('description'))
return data
raise RuntimeError('Telegram Bot API: wyczerpane próby dla ' + method)Co robi ta funkcja. Przy błędzie sieciowym czeka wykładniczo: 1, 2, 4, 8 sekund, ale nie więcej niż 30. Dzięki temu bot przeżywa zmianę IP na proxy lub krótkie zerwanie kanału. Przy 429 czyta retry_after, dodaje pół sekundy zapasu i powtarza. Przy błędach 5xx po stronie Telegramu też powtarza z pauzą. Przy błędach 400 lub 403, na przykład jeśli użytkownik zablokował bota, powtórzenie jest bezcelowe, więc funkcja zwraca odpowiedź taką, jaka jest, a Ty decydujesz, co dalej.
Ograniczamy szybkość z góry
Lepiej wcale nie doprowadzać do 429. Dla rozsyłek dodaj pauzę między wiadomościami. Najprostszy wariant: time.sleep(0.05) po każdej wysyłce daje 20 wiadomości na sekundę, co jest poniżej ogólnego limitu. Dla jednego czatu trzymaj pauzę nie mniejszą niż sekunda. Dla grup nie częściej niż 20 wiadomości na minutę.
def broadcast(chat_ids, text):
sent, failed = 0, 0
for cid in chat_ids:
res = call('sendMessage', {'chat_id': cid, 'text': text})
if res.get('ok'):
sent += 1
else:
failed += 1
time.sleep(0.05)
print('Wysłano:', sent, 'Błędów:', failed)Wskazówka: Zapisuj odpowiedzi z błędem 403 Forbidden: bot was blocked by the user. Usuwaj takich użytkowników z bazy rozsyłki. Zmniejszy to obciążenie i ochroni przed zbędnymi limitami, bo nieudane żądania też się liczą.
Testujemy obsługę 429
- Utwórz grupę testową i dodaj do niej bota.
- Uruchom pętlę 40 wywołań
call('sendMessage', {...})do tego czatu bez pauz. - Obserwuj w konsoli: po kilku szybkich wysyłkach pojawi się wiersz o 429 i czasie oczekiwania.
- Upewnij się, że po pauzie wysyłka jest kontynuowana i wszystkie 40 wiadomości dotarło.
Sprawdzenie: Wszystkie wiadomości dostarczone, bot nie padł z wyjątkiem, w logu widać pauzy retry_after. Zastąp requests.post w polling.py i webhook.py funkcją call, aby cała praca z Telegram Bot API szła przez jeden chroniony kanał.
Możliwe problemy
- retry_after ogromny, setki sekund. Długo ignorowałeś limit. Zatrzymaj wysyłkę całkowicie, odczekaj wskazany czas i zmniejsz tempo.
- 429 przychodzi już przy pierwszych wiadomościach. Inny proces używa tego samego tokenu. Sprawdź, czy nie jest uruchomiona stara wersja bota.
- Odpowiedź nie jest JSON przy 429. Niektóre proxy zwracają własną stronę HTML z błędem. Owiń r.json() w try i przy niepowodzeniu czekaj ustalone 5 sekund.
Krok 6: Zaawansowane ustawienia dla obciążonych projektów
Cel etapu: przygotować bota do wzrostu: kilka botów przez kilka proxy, kolejka wysyłki, lokalny serwer Bot API i rozsądna rotacja. Początkujący mogą pominąć tę sekcję i wrócić, gdy użytkowników będzie ponad tysiąc.
Kilka botów przez różne proxy
Marketerzy często prowadzą dziesięć botów dla różnych projektów z jednego serwera. Właściwa architektura: dla każdego bota własny słownik proxies i własna sesja requests.Session(). Sesja ponownie wykorzystuje połączenia TCP, co zmniejsza obciążenie proxy i przyspiesza żądania 2-3 razy. Przechowuj konfigurację jako listę: token, adres proxy, tryb odbioru aktualizacji. Jeden proces na bota jest łatwiejszy w debugowaniu niż jeden proces na wszystkie.
Kolejka wysyłki zamiast bezpośrednich wywołań
Dla rozsyłek od 10 tysięcy użytkowników bezpośrednie wywołania z głównego kodu przestają działać. Zorganizuj kolejkę: Redis lub przynajmniej tabelę w bazie z polami chat_id, text, status, attempts. Osobny worker pobiera zadania i wywołuje funkcję call z kontrolą szybkości. Przy 429 worker śpi, a nie blokuje odbioru webhooków. Dzięki temu bot nadal odpowiada na polecenia użytkowników, podczas gdy rozsyłka idzie w tle. W 2026 roku Telegram Bot API pozwala płatnym botom przez parametr allow_paid_broadcast podnieść limit do 1000 wiadomości na sekundę, ale za to pobiera się Stars, więc dla większości projektów kolejka z 20-25 wiadomościami na sekundę pozostaje optymalnym wariantem.
Lokalny serwer Bot API
Telegram publikuje źródła serwera Bot API, który można uruchomić u siebie. Twój kod zwraca się wtedy nie do api.telegram.org, ale do localhost, a sam lokalny serwer komunikuje się z Telegramem. Plusy: przesyłanie plików do 2 GB zamiast 50 MB, webhooki na dowolny port i bez HTTPS w Twojej sieci, zniesienie niektórych limitów. Minus: proxy trzeba skonfigurować na poziomie samego lokalnego serwera, a nie w kodzie bota. Wariant dla zespołów z kompetencjami DevOps, na start zbędny.
Rotacja IP a webhooki
Przy webhookach rotacja IP na proxy jest prawie niezauważalna: każde wywołanie sendMessage jest krótkie, a zerwanie połączenia w momencie zmiany dotknie co najwyżej jednego żądania, które otoczka call powtórzy. Dlatego dla webhooków dopuszczalna jest częstsza rotacja niż dla pollingu. Niemniej sensu w częstej zmianie nie ma: Telegram Bot API nie ogranicza żądań po IP, a limity są związane z tokenem. Ustawiaj rotację z powodów swojej infrastruktury, a nie dla API.
Monitoring zdrowia bez osobnego systemu
Minimalny zestaw, który warto założyć od razu: raz na minutę wywołuj getWebhookInfo i zapisuj w logu pending_update_count i last_error_message. Jeśli kolejka rośnie w trzech kolejnych pomiarach, Twój handler nie wyrabia. Dla pollingu zapisuj czas ostatniego udanego getUpdates: jeśli minęły ponad dwie minuty, połączenie zawisło, zrestartuj proces. To wystarczy, by dowiadywać się o problemach wcześniej niż klienci.
Wskazówka: Loguj nie tylko błędy, ale i czas każdego żądania do Telegram Bot API przez proxy. Powolny wzrost średniego czasu odpowiedzi z 0,3 do 2 sekund ostrzeże o degradacji kanału na dni przed tym, jak bot zacznie gubić wiadomości.
Sprawdzenie rezultatu: lista kontrolna gotowego rozwiązania
Przejdź przez listę. Każdy punkt musi być odhaczony, tylko wtedy bota można uznać za gotowego do pracy z rzeczywistymi użytkownikami.
Lista kontrolna
- Polecenie curl z parametrem -x przez proxy zwraca
"ok":truena metodę getMe. - Skrypt check.py pokazuje IP proxy, a nie Twoje własne.
- Polling odpowiada na wiadomość raz, bez duplikatów.
- Po zatrzymaniu i ponownym uruchomieniu pollingu pominięte wiadomości są obsługiwane.
- Przy wymuszonej zmianie IP na proxy polling wraca sam w 3-5 sekund.
- Webhook: getWebhookInfo pokazuje Twój url, zerowy pending_update_count i puste last_error_message.
- Żądanie do webhooka bez nagłówka sekretnego otrzymuje 403.
- Szybka wysyłka 40 wiadomości do jednego czatu przechodzi bez padnięcia, w logu widać pauzy retry_after.
- Token i dane proxy leżą w .env, a nie w kodzie.
Jak przetestować całość
- Uruchom bota w wybranym trybie.
- Napisz do niego z trzech różnych kont po dwie wiadomości.
- Upewnij się, że jest sześć odpowiedzi, po jednej na każdą wiadomość.
- Naciśnij w panelu proxy link zmiany IP i od razu wyślij jeszcze jedną wiadomość.
- Bot powinien odpowiedzieć w ciągu 10 sekund.
- Uruchom test na 429 z kroku 5.
- Sprawdź logi: brak nieobsłużonych wyjątków i śladów stosu.
Wskaźniki sukcesu
Czas odpowiedzi bota na wiadomość do 2 sekund. Udział nieudanych żądań do Telegram Bot API po wszystkich powtórzeniach poniżej 0,1 procenta. Ani jednego duplikatu w ciągu doby pracy. pending_update_count w getWebhookInfo nie przekracza dziesięciu w godzinach szczytu. Jeśli wskaźniki się zgadzają, gratulacje: zbudowałeś niezawodny schemat, który wystarczy na długie miesiące.
Typowe błędy i ich rozwiązania
Błąd 409 Conflict przy getUpdates
Przyczyna: dla bota ustawiony jest webhook albo uruchomione są dwa egzemplarze pollingu. Rozwiązanie: wywołać deleteWebhook przez proxy, upewnić się, że działa tylko jeden proces. Sprawdź polecenie ps aux | grep polling.
Bot odpowiada dwa razy na każdą wiadomość
Przyczyna: offset się nie zwiększa lub uruchomione są dwie kopie bota na różnych serwerach z jednym tokenem. Rozwiązanie: sprawdź wiersz offset = update_id + 1, zatrzymaj zbędne kopie. Dla webhooka upewnij się, że nginx nie duplikuje żądań do dwóch backendów.
Błąd 407 Proxy Authentication Required
Przyczyna: błędne dane uwierzytelniające proxy lub niezakodowane znaki specjalne w haśle. Rozwiązanie: ponownie sprawdź login i hasło w panelu, zakoduj @, : i / w haśle, spróbuj autoryzacji po IP, jeśli jest dostępna w Twojej taryfie.
Read timed out co 50-60 sekund
Przyczyna: timeout pollingu jest większy lub równy timeoutowi bezczynności na proxy. Rozwiązanie: zmniejsz timeout w getUpdates do 30-40 sekund, a timeout klienta trzymaj o 10 sekund większy.
Webhook ustawiony, ale aktualizacje nie przychodzą
Przyczyna: port zamknięty, certyfikat nieprawidłowy lub handler odpowiada nie 200. Rozwiązanie: patrz na last_error_message w getWebhookInfo, to dokładna diagnoza. Sprawdź curl -I https://bot.example.com/tg/webhook z innego komputera.
Wrong response from the webhook: 403 Forbidden
Przyczyna: token sekretny w kodzie różni się od przekazanego w setWebhook. Rozwiązanie: zainstaluj webhook ponownie z tą samą wartością, co w kodzie. Pamiętaj, że setWebhook z nowymi parametrami całkowicie zastępuje poprzednie.
Ciągłe 429 przy niewielkim obciążeniu
Przyczyna: bot wysyła do jednego czatu częściej niż raz na sekundę, na przykład kilka wiadomości pod rząd w odpowiedzi na jedno polecenie. Rozwiązanie: łącz odpowiedzi w jedną wiadomość, używaj editMessageText zamiast nowych wiadomości do postępu, dodaj pauzę między wysyłkami do jednego chat_id.
Ruch idzie bezpośrednio, omijając proxy
Przyczyna: w słowniku proxies nie ma klucza https, zmienna środowiskowa nie jest widoczna dla procesu, framework nie podchwycił ustawienia. Rozwiązanie: sprawdź wychodzący IP żądaniem do api.ipify.org w tym samym kodzie, którym wysyłasz wiadomości. Nie ufaj przypuszczeniom, sprawdzaj faktycznie.
SSL: CERTIFICATE_VERIFY_FAILED przy żądaniach przez proxy
Przyczyna: przestarzały zestaw certyfikatów głównych lub błędny czas systemowy. Rozwiązanie: zaktualizuj certifi, zsynchronizuj czas. Nigdy nie wyłączaj weryfikacji certyfikatów parametrem verify=False: otwiera to możliwość podmiany ruchu z tokenem.
FAQ: częste pytania o konfigurację
Co wybrać na start: polling czy webhook?
Polling. Działa z dowolnego miejsca, nie wymaga domeny ani certyfikatu, a na webhook można przełączyć się później w ciągu godziny. Webhook ma sens, gdy bot obsługuje tysiące użytkowników lub działa na serwerze, gdzie HTTPS już jest.
Czy można użyć jednego proxy dla kilku botów?
Tak. Limity Telegram Bot API są przypisane do tokenu bota, a nie do IP. Dziesięć botów przez jedno proxy nie przeszkadza sobie nawzajem z punktu widzenia API. Jedynym ograniczeniem jest przepustowość samego proxy, dla botów tekstowych wystarcza z dużym zapasem.
Czy trzeba przepuszczać przez proxy zarówno webhook, jak i odpowiedzi?
Przychodzące żądania webhooka docierają bezpośrednio na Twój serwer, przez proxy nie da się ich przepuścić z definicji. Przez proxy idą tylko wywołania wychodzące: sendMessage, setWebhook, getFile i pozostałe metody. To normalny i jedyny możliwy schemat.
Jak sprawdzić, że żądania naprawdę idą przez proxy?
W tym samym kodzie zapytaj https://api.ipify.org z tymi samymi ustawieniami proxies i porównaj z Twoim rzeczywistym IP. Dodatkowo możesz spojrzeć na statystyki ruchu w panelu proxy: licznik powinien rosnąć podczas pracy bota.
Co robić przy zmianie IP na proxy podczas pracy bota?
Nic, jeśli użyłeś kodu z tego przewodnika. Polling przechwyci zerwanie połączenia i kontynuuje od zapisanego offset. Funkcja call powtórzy nieudane żądanie. Jedyna rada: nie ustawiaj rotacji częściej niż raz na kilka minut dla trybu pollingu.
SOCKS5 czy proxy HTTP dla Telegram Bot API?
Dla bota różnicy prawie nie ma, oba działają. Proxy HTTP jest łatwiejsze w konfiguracji i obsługiwane przez wszystkich klientów bez dodatkowych pakietów. SOCKS5 jest wygodniejsze, gdy chcesz zagwarantować rozwiązywanie DNS po stronie proxy przez schemat socks5h. Wybierz to, czego już używasz w innych projektach.
Ile wiadomości można wysyłać, by nie dostać 429?
Trzymaj się orientacyjnych wartości: do 1 wiadomości na sekundę do czatu prywatnego, do 20 na minutę do grupy, do 25-30 na sekundę łącznie. Dla masowych rozsyłek zakładaj 20 wiadomości na sekundę i koniecznie obsługuj retry_after, bo limity mogą tymczasowo spadać przy dużym obciążeniu Telegramu.
Jak bezpiecznie przenieść już działającego bota na proxy?
Najpierw sprawdź proxy przez curl na getMe. Następnie dodaj zmienną HTTPS_PROXY lub skonfiguruj proxies w kodzie, uruchom bota na tokenie testowym. Dopiero po udanych sprawdzeniach przełącz token produkcyjny. Trzymaj starą konfigurację pod ręką do wycofania zmian.
Jak wycofać webhook i wrócić do pollingu?
Jedno wywołanie deleteWebhook przez proxy. Jeśli chcesz zachować nagromadzone aktualizacje dla pollingu, nie przekazuj drop_pending_updates. Następnie uruchom polling.py, a bot podchwyci kolejkę.
Czy można ustawić kilka URL webhooka dla jednego bota?
Nie, bot ma dokładnie jeden webhook. Jeśli trzeba rozłożyć obciążenie, postaw za jedynym URL balanser nginx, który rozrzuca żądania po kilku egzemplarzach aplikacji. Dla Telegramu wygląda to jak jeden punkt wejścia.
Zakończenie
Podsumujmy wykonaną pracę. Utworzyłeś bota i zdobyłeś token, nauczyłeś się sprawdzać proxy przez curl i Pythona, upewniłeś się, że ruch do Telegram Bot API idzie właściwą trasą. Zbudowałeś odporną pętlę długiego pollingu, która przeżywa zmianę IP i nie duplikuje wiadomości. Postawiłeś webhook z prawdziwym certyfikatem HTTPS i zabezpieczyłeś go tokenem sekretnym. I co najcenniejsze: napisałeś jedną funkcję, która respektuje retry_after przy 429, powtarza żądania przy awariach sieci i zamienia kapryśny kanał w niezawodny.
Co dalej. Przygotuj bota jako usługę systemd, aby podnosił się po restarcie serwera. Przenieś tokeny i adresy proxy do zmiennych środowiskowych na maszynie produkcyjnej. Dodaj prosty log czasów odpowiedzi i raz w tygodniu go przeglądaj. Jeśli użytkowników robi się dużo, przejdź do kolejki wysyłki z zaawansowanej sekcji.
Kierunki rozwoju. Poznaj metody Telegram Bot API dla przycisków inline, płatności i mini-aplikacji, otwierają one przed botami zupełnie nowe scenariusze dla marketingu i sprzedaży. Opanuj asynchroniczne frameworki aiogram lub python-telegram-bot, przejmą one rutynę pollingu i powtórzeń, a Ty już rozumiesz, co dzieje się pod ich maską. I najważniejsze: nie bój się eksperymentować na bocie testowym. Każdy błąd 429 czy 409, który sam złapałeś i naprawiłeś, czyni Cię silniejszym niż jakikolwiek gotowy szablon. Uda Ci się.