Содержание
  1. Готовый бот или свой: когда код не понадобится
  2. Начало работы: токен у BotFather и окружение
  3. Настройка проекта
  4. Какой погодный API выбрать для бота
  5. Получение данных о погоде
  6. Разработка функционала бота: пример кода на aiogram 3
  7. Тот же бот на python-telegram-bot
  8. Обработка запросов пользователя
  9. Улучшение функционала: пример кода для уведомлений о погоде
  10. Тестирование и отладка
  11. Куда выложить бота, чтобы он работал круглосуточно
  12. Вопросы и ответы
  13. Заключение
ГайдыОбновлено · 08.2026

Создание телеграм-бота с прогнозом погоды

24 апреля 2024 · 15 минут чтения

Погода в телеграмме приходит от бота, которого можно собрать за вечер: зарегистрируйте бота у @BotFather, возьмите токен, запросите погодный API по названию города и отправьте ответ пользователю. Файл бота на aiogram 3 умещается в 35 строк Python. API-ключ нужен не всегда: Open-Meteo отвечает без регистрации.

Коротко о том, что внутри:

  • чем готовый погодный бот отличается от своего и когда код вообще не понадобится;
  • сравнение трёх погодных API по лимитам бесплатного доступа — Open-Meteo, OpenWeatherMap, Яндекс Погода;
  • рабочий код под версии, актуальные на август 2026 года: aiogram 3.30.0 и python-telegram-bot 22.8;
  • обработка опечаток в названии города и обрывов сети;
  • ежедневная рассылка прогноза по расписанию и вывод бота на сервер.

Готовый бот или свой: когда код не понадобится

Если задача звучит как «хочу видеть прогноз прямо в мессенджере», писать ничего не придётся — публичные погодные боты в Telegram уже работают. Пример — @meteonovabot службы МЕТЕОНОВА: на официальной странице сервиса сказано, что приложение «показывает погоду сейчас и прогноз на 3 дня по любому из 45 тысяч городов мира». Такой бот открывается по ссылке и работает сразу; набор возможностей ограничен тем, что заложил автор.

Свой бот выигрывает там, где чужой упирается в потолок:

  • уведомление приходит по вашему условию — заморозки ночью, дождь к часу выезда, ветер выше 15 м/с;
  • прогноз публикуется в ваш канал или рабочий чат по расписанию;
  • погода склеивается с другими данными: расписанием доставки, показаниями датчиков, календарём работ;
  • формулировки ответа и язык — ваши.

Готовые боты Telegram под разные задачи мы разбирали в обзоре бесплатных ботов для обработки фото. Если программировать не хочется совсем, посмотрите разбор конструкторов чат-ботов. Дальше в статье — путь для тех, кому нужен свой.

Начало работы: токен у BotFather и окружение

Бот регистрируется у @BotFather — служебного бота Telegram. По документации Telegram команда /newbot запускает диалог: BotFather спрашивает имя и юзернейм, после чего выдаёт токен авторизации. Требования к юзернейму там же: длина 5–32 символа, только латиница, цифры и подчёркивание, окончание обязательно на «bot». Поменять юзернейм потом нельзя, поэтому выбирайте сразу.

Токен выглядит как строка вида 110201543:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw. Справка Telegram предупреждает: тот, у кого есть токен, управляет ботом, — значит, в публичный репозиторий его класть нельзя, только в переменную окружения или отдельный файл конфигурации.

Актуальная версия протокола на момент публикации — Bot API 10.2 от 14 июля 2026 года. Документация aiogram заявляет поддержку Bot API 10.2, документация python-telegram-bot — Bot API 10.0; для погодного бота разница между ними роли не играет, обе версии умеют всё нужное.

Настройка проекта

Путь от нуля до работающего погодного бота
Путь от нуля до работающего погодного бота

Документация python-telegram-bot требует Python 3.10 и новее; тот же интерпретатор подойдёт и для aiogram 3. Если Python на компьютере ещё не стоит, начните с гайда как запустить Python IDLE и написать первый код.

python -m venv venv
venv\Scripts\activate        # Windows
source venv/bin/activate     # macOS и Linux

pip install aiogram requests
# либо второй вариант из статьи:
pip install "python-telegram-bot[job-queue]" requests

Виртуальное окружение здесь не формальность: две библиотеки для Telegram в одном системном Python рано или поздно столкнутся зависимостями.

Какой погодный API выбрать для бота

Гайды по теме почти поголовно берут OpenWeatherMap и на этом останавливаются. Условия бесплатного доступа у погодных сервисов пересматриваются, поэтому перед выбором стоит сверить три варианта по одному признаку: что вы получаете без карты и без договора. Данные ниже сняты со страниц самих сервисов в августе 2026 года.

Сервис Нужен ли ключ Бесплатный доступ Коммерческое использование
Open-Meteo Нет. Справка сервиса указывает, что ключ требуется только для коммерческого доступа к выделенным ресурсам 10 000 запросов в сутки, 5 000 в час, 300 000 в месяц На бесплатном тарифе отмечено крестиком
OpenWeatherMap Да, ключ выдаётся после регистрации «1,000 API calls per day for free» по модели Pay as you call, ограничение 60 запросов в минуту По платным тарифам
Яндекс Погода Да, через Личный кабинет «Погоды для бизнеса» «Чтобы попробовать бесплатно в течение 7-ми дней, получите доступ в Личный кабинет Погоды для бизнеса» По тарифам сервиса

Считаем на пальцах: личный бот с десятком пользователей делает от силы несколько сотен запросов в сутки, и в лимит Open-Meteo он укладывается с многократным запасом, а в тысячу вызовов OpenWeatherMap — уже впритык, если добавить утреннюю рассылку. Отсюда выбор для учебного и домашнего проекта: Open-Meteo, потому что он снимает главный барьер новичка — регистрацию, ключ и привязку карты. OpenWeatherMap оправдан, когда нужны его карты-слои и историческая база. Яндекс Погода — вариант для компании с договором.

Получение данных о погоде

Что происходит, когда пользователь пишет боту «Казань»
Что происходит, когда пользователь пишет боту «Казань»

Open-Meteo работает по координатам, поэтому названию города сначала нужно найти широту и долготу. За это отвечает отдельный геокодер. По справке Open-Meteo адрес геокодера — https://geocoding-api.open-meteo.com/v1/search, обязательный параметр name принимает название населённого пункта или почтовый индекс, необязательные count, language и format; ответ содержит latitude, longitude, name и country. Сам прогноз отдаёт эндпоинт https://api.open-meteo.com/v1/forecast, а список текущих величин перечисляется в параметре current.

Состояние неба приходит числом — кодом WMO. Справка Open-Meteo расшифровывает его так: 0 — «Clear sky», 1, 2, 3 — «Mainly clear, partly cloudy, and overcast», 45, 48 — «Fog and depositing rime fog», 61, 63, 65 — «Rain: Slight, moderate and heavy intensity», 71, 73, 75 — «Snow fall: Slight, moderate, and heavy intensity», 95 — «Thunderstorm: Slight or moderate». Русские подписи придётся собрать самому — вот минимальный словарь и функция запроса:

import requests

GEO = "https://geocoding-api.open-meteo.com/v1/search"
FORECAST = "https://api.open-meteo.com/v1/forecast"

WMO = {
    0: "ясно",
    1: "малооблачно", 2: "переменная облачность", 3: "пасмурно",
    45: "туман", 48: "изморозь",
    51: "слабая морось", 53: "морось", 55: "сильная морось",
    61: "небольшой дождь", 63: "дождь", 65: "сильный дождь",
    71: "небольшой снег", 73: "снег", 75: "сильный снег",
    80: "ливень", 81: "ливень", 82: "сильный ливень",
    95: "гроза", 96: "гроза с градом", 99: "гроза с градом",
}


def get_weather(city: str) -> str:
    geo = requests.get(
        GEO, params={"name": city, "count": 1, "language": "ru"}, timeout=10
    ).json()
    if not geo.get("results"):
        return f"Город «{city}» найти не удалось. Проверьте написание."

    place = geo["results"][0]
    data = requests.get(FORECAST, params={
        "latitude": place["latitude"],
        "longitude": place["longitude"],
        "current": "temperature_2m,apparent_temperature,weather_code,wind_speed_10m",
        "timezone": "auto",
    }, timeout=10).json()

    now = data["current"]
    sky = WMO.get(now["weather_code"], "без описания")
    return (
        f"{place['name']}: {sky}, {now['temperature_2m']:.0f} °C, "
        f"ощущается как {now['apparent_temperature']:.0f} °C, "
        f"ветер {now['wind_speed_10m']:.0f} км/ч"
    )

Сохраните этот код файлом weather.py — оба варианта бота ниже импортируют из него одну функцию. Проверить её можно без Telegram: print(get_weather("Казань")) в консоли.

Разработка функционала бота: пример кода на aiogram 3

aiogram — асинхронный фреймворк, на котором держится большая часть русскоязычных ботов. Живая ветка — третья: документация описывает версию 3.30.0 и поддержку Telegram Bot API 10.2. Код из aiogram 2 на ней падает — декоратор @dp.message_handler и executor.start_polling из старых гайдов там отсутствуют. Ориентир простой: если в примере из интернета есть executor, пример устарел.

import asyncio

from aiogram import Bot, Dispatcher
from aiogram.filters import CommandStart
from aiogram.types import Message

from weather import get_weather

TOKEN = "ВАШ_ТОКЕН_ОТ_BOTFATHER"

dp = Dispatcher()


@dp.message(CommandStart())
async def command_start(message: Message) -> None:
    await message.answer("Пришлите название города — верну текущую погоду.")


@dp.message()
async def city_handler(message: Message) -> None:
    city = (message.text or "").strip()
    if not city:
        await message.answer("Нужно название города текстом.")
        return
    text = await asyncio.to_thread(get_weather, city)
    await message.answer(text)


async def main() -> None:
    bot = Bot(token=TOKEN)
    await dp.start_polling(bot)


if __name__ == "__main__":
    asyncio.run(main())

Одна деталь, которую пропускают почти все туториалы: requests блокирует поток, и внутри асинхронного обработчика он останавливает весь бот на время запроса к погодному сервису. Пока пользователь один, это незаметно; на десятке одновременных запросов бот начинает отвечать с задержкой. Поэтому вызов завёрнут в asyncio.to_thread — так цикл событий остаётся свободным. Альтернатива — переписать функцию на aiohttp.

Запуск: python bot.py. Бот отвечает в личке сразу после старта, деплой для проверки не нужен.

Тот же бот на python-telegram-bot

Библиотека, с которой начинали большинство старых гайдов, тоже сменила мажорную версию. Стабильная документация описывает python-telegram-bot v22.8 с поддержкой Bot API 10.0 и требует Python 3.10 или новее. Примеры из веток 12–13 на ней не запускаются: Updater с dispatcher.add_handler и синхронные функции-обработчики заменены на Application и корутины.

from telegram import Update
from telegram.ext import (
    Application, CommandHandler, ContextTypes, MessageHandler, filters,
)

from weather import get_weather

TOKEN = "ВАШ_ТОКЕН_ОТ_BOTFATHER"


async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    await update.message.reply_text("Пришлите название города — верну текущую погоду.")


async def city_handler(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    await update.message.reply_text(get_weather(update.message.text))


def main() -> None:
    app = Application.builder().token(TOKEN).build()
    app.add_handler(CommandHandler("start", start))
    app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, city_handler))
    app.run_polling()


if __name__ == "__main__":
    main()

Фильтр filters.TEXT & ~filters.COMMAND отсекает команды от обычного текста: без него бот попытается искать погоду в городе с названием «/start». Метод run_polling сам поднимает и закрывает цикл событий, отдельный asyncio.run здесь лишний.

Выбор между двумя библиотеками сводится к привычке. aiogram ближе тем, кто пишет асинхронный код и хочет фильтры-декораторы; python-telegram-bot даёт встроенный планировщик задач, который пригодится в следующем разделе.

Обработка запросов пользователя

Пользователь пишет боту как человеку, поэтому на вход прилетает всё подряд. Четыре ситуации ломают наивный код чаще остальных:

  • Опечатка или несуществующий город. Геокодер Open-Meteo возвращает ответ без ключа results. Проверка if not geo.get("results") из примера выше закрывает этот случай; без неё бот падает с KeyError.
  • Тёзки. Параметр count: 1 берёт первое совпадение, а городов с одинаковым названием хватает: Ростов, Владимир, Никольское. Поднимите count до 5 и покажите варианты кнопками — тогда выбор делает пользователь.
  • Лишние символы в строке. Пробелы по краям, эмодзи и фразы вроде «погода в Казани» прилетают в то же поле message.text. Минимум — .strip() перед отправкой в геокодер; дальше можно вырезать предлоги простым правилом или списком стоп-слов.
  • Обрыв сети. Запрос без timeout способен подвесить обработчик на минуты. Таймаут в примере стоит на обоих вызовах; сам вызов имеет смысл обернуть в try/except requests.RequestException и ответить человеку понятной фразой.

Отдельная мелочь, которая всплывает на первом же тесте: сообщения от команд и от обычного текста ловятся разными обработчиками. В aiogram порядок регистрации важен — обработчик @dp.message() без фильтра перехватывает всё, что не разобрали предыдущие, поэтому он должен идти последним.

Три проверки — пустая строка, пустой results, таймаут — снимают почти все падения учебного бота.

Улучшение функционала: пример кода для уведомлений о погоде

Рассылка прогноза по расписанию — первое, что просят добавить после запуска. В python-telegram-bot за это отвечает JobQueue. Планировщик ставится отдельным экстра: pip install "python-telegram-bot[job-queue]" — по документации библиотеки этот набор подтягивает APScheduler и нужен для работы telegram.ext.JobQueue.

Сигнатура метода из справки библиотеки: run_daily(callback, time, days=(0, 1, 2, 3, 4, 5, 6), data=None, name=None, chat_id=None, user_id=None, job_kwargs=None). Дни недели считаются от нуля, где ноль — воскресенье. Внутри обработчика доступны job.chat_id, job.data и job.name.

import datetime as dt
from zoneinfo import ZoneInfo

from telegram.ext import Application, ContextTypes

from weather import get_weather

MSK = ZoneInfo("Europe/Moscow")


async def morning_forecast(context: ContextTypes.DEFAULT_TYPE) -> None:
    city = context.job.data
    await context.bot.send_message(
        chat_id=context.job.chat_id,
        text=get_weather(city),
    )


def schedule_morning(app: Application, chat_id: int, city: str) -> None:
    app.job_queue.run_daily(
        morning_forecast,
        time=dt.time(hour=8, minute=0, tzinfo=MSK),
        chat_id=chat_id,
        data=city,
        name=f"forecast-{chat_id}",
        days=(1, 2, 3, 4, 5),          # с понедельника по пятницу
    )

Часовой пояс через ZoneInfo здесь обязателен. Без tzinfo время трактуется по настройке приложения, и на сервере в UTC «восемь утра» превращается в одиннадцать по Москве — классическая причина писем «бот шлёт прогноз ночью».

Имя задания name=f"forecast-{chat_id}" нужно, чтобы позже найти и снять рассылку по команде /stop: одна запись в JobQueue соответствует одному чату, и без уникального имени вы их не различите.

Тестирование и отладка

Погодный бот ломается в трёх местах: на стороне Telegram, на стороне погодного API и на разборе пользовательской строки. Разделять их проще всего так:

  • сначала проверьте get_weather отдельным скриптом, без Telegram — если она возвращает текст, погодная часть жива;
  • откройте адрес запроса прямо в браузере и посмотрите сырой JSON: это быстрее, чем ставить брейкпоинты;
  • держите одну запущенную копию процесса с одним токеном — два параллельных опроса конфликтуют между собой, и бот начинает отвечать через раз;
  • прогоните список входных строк: пустая, с пробелами, с эмодзи, латиницей, несуществующим городом, очень длинная;
  • логируйте сырые ответы погодного API вместе с сообщениями бота: при смене формата ответа сервисом этот лог остаётся единственным следом.

Пять минут на этот чек-лист экономят вечер поисков «почему бот молчит».

Куда выложить бота, чтобы он работал круглосуточно

Пока скрипт запущен на вашем компьютере, бот жив ровно до закрытия крышки ноутбука. Документация Bot API описывает два способа получать обновления: опрос методом getUpdates (его и делает start_polling или run_polling) и вебхук через setWebhook, когда Telegram сам стучится на ваш HTTPS-адрес.

Для учебного бота хватит опроса на самом дешёвом VPS: разворачиваете виртуальное окружение, кладёте токен в переменные окружения, оформляете запуск службой systemd с автоперезапуском. Вебхук выигрывает на нагрузке и требует домена с сертификатом, поэтому переходить на него имеет смысл, когда пользователей станут сотни.

Тот же каркас — токен, обработчики, деплой — работает и для более сложных ботов. Как к нему прикручивается языковая модель, разобрано в статье создание Telegram-бота на основе GPT.

Вопросы и ответы

Какой готовый бот показывает погоду в Телеграмм?

Публичных погодных ботов в мессенджере несколько. Официальная страница службы МЕТЕОНОВА описывает бот @meteonovabot так: приложение показывает погоду сейчас и прогноз на 3 дня по любому из 45 тысяч городов мира. Готовый бот подключается одним нажатием, но набор функций у него фиксированный: свои условия уведомлений и публикацию прогноза в собственный канал он не закроет.

Нужен ли API-ключ, чтобы бот отдавал прогноз погоды?

Зависит от сервиса. Справка Open-Meteo указывает, что ключ требуется только для коммерческого доступа к выделенным ресурсам, поэтому учебный бот обходится без регистрации. OpenWeatherMap выдаёт ключ после регистрации аккаунта. Яндекс Погода работает через Личный кабинет «Погоды для бизнеса» с пробным периодом 7 дней.

На какой версии библиотеки писать телеграм-бота в 2026 году?

Актуальные ветки — aiogram 3 и python-telegram-bot 22. Документация aiogram описывает версию 3.30.0 с поддержкой Telegram Bot API 10.2, стабильная документация python-telegram-bot — версию 22.8 с поддержкой Bot API 10.0 и требованием Python 3.10 или новее. Примеры с executor.start_polling из aiogram 2 и с Updater из python-telegram-bot 13 на этих версиях уже не запускаются.

Сколько бесплатных запросов хватит погодному боту?

Бесплатный доступ Open-Meteo — 10 000 запросов в сутки, 5 000 в час и 300 000 в месяц, коммерческое использование на нём не разрешено. У OpenWeatherMap на бесплатном плане заявлена 1 000 вызовов в сутки при ограничении 60 запросов в минуту. Личному боту с десятком пользователей этого хватает с запасом даже при ежедневной утренней рассылке.

Почему бот запускается, но молчит в чате?

Три частые причины. Запущены две копии процесса с одним токеном — параллельные опросы Telegram конфликтуют. Обработчик обычного текста зарегистрирован раньше командных, поэтому перехватывает всё подряд. Запрос к погодному API висит без таймаута, и ответ не успевает уйти. Проверять начинайте с функции получения погоды отдельным скриптом: если она молчит, дело за пределами Telegram.

Заключение

Телеграм-бот с прогнозом погоды — короткий проект с честным результатом: на выходе рабочий инструмент, которым пользуются каждый день. Схема одна и та же независимо от библиотеки: токен у BotFather, функция обращения к погодному API, обработчик сообщения, запуск на сервере. Дальше её можно наращивать — кнопки с городами, прогноз на неделю, оповещения о заморозках, публикация в канал.

Читайте также

3 материала