videoDownloadTGbot/instagram-downloader
vrubelroman c9972f3d68
All checks were successful
CI/CD Pipeline / build-and-deploy (push) Successful in 52s
fix(cookies): не давать yt-dlp затирать мастер-файл кук, честнее алерты
Реальный инцидент: cookies "протухли" за пару дней вместо ~года. Причина —
не срок годности, а сам yt-dlp: --cookies FILE читает И дописывает cookie
jar обратно в файл после каждого запуска (--help: "read cookies from and
dump cookie jar in"), а когда Instagram-экстрактор решает, что сессия
невалидна, он явно чистит sessionid из jar'а — и это тут же сохраняется на
диск через YoutubeDL.close(). Наш собственный health-check (каждые 30 мин)
и обычные скачивания медленно, но верно стирали себе рабочие cookies.

Фикс: yt-dlp больше никогда не видит мастер-файл, только одноразовую копию
в фиксированном /tmp-пути (безопасно — оба сервиса --workers=1, гонок нет).
Проверено: md5sum/mtime мастер-файлов не меняются ни после серии
/cookies/check, ни после реального /download/stream.

Заодно в bot.py: notify_admin_cookie_alert больше не заявляет "это НЕ
cookies" для extraction_failed — на практике это оказалось не всегда
верно (анонимный rate-limit тоже "не cookies" по факту, но валидная
сессия могла бы его обойти). В алерты добавлена проверяемая ссылка
(test_url из /cookies/check), чтобы сразу было видно, что это health-check
дёргает тестовый ролик, а не реальная ссылка пользователя. Новый статус
cookies_incomplete детектирует "файл есть, но sessionid нет" ещё до
сетевых проверок — ловит именно тот случай, что привёл к инциденту.

Отдельно: пользователю теперь показывается понятное сообщение, когда
Instagram сам блокирует контент как возрастной/чувствительный
("can't be seen by certain audiences") — вместо общего "Something went
wrong", раз повторная попытка всё равно не поможет. Админ по-прежнему
получает полный технический текст без изменений.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-31 15:18:13 +00:00
..
app.py fix(cookies): не давать yt-dlp затирать мастер-файл кук, честнее алерты 2026-07-31 15:18:13 +00:00
docker-compose.yml Fix YouTube 500 error (n-challenge) and Telegram callback_data overflow 2026-04-30 17:21:10 +03:00
Dockerfile add admin bot 2025-12-20 22:17:20 +03:00
instagram_cookies.txt fix(cookies): mount youtube/instagram cookies from host instead of baking into image 2026-06-30 22:02:14 +00:00
INSTAGRAM_COOKIES_INSTRUCTIONS.md fix(downloaders): Deno runtime, свежий yt-dlp, честный health-check, смоук-тест 2026-07-26 00:31:16 +00:00
README.md fix(downloaders): Deno runtime, свежий yt-dlp, честный health-check, смоук-тест 2026-07-26 00:31:16 +00:00
requirements.txt fix(downloaders): Deno runtime, свежий yt-dlp, честный health-check, смоук-тест 2026-07-26 00:31:16 +00:00

Instagram Downloader Service

Микросервис для скачивания видео с Instagram.

Требования

  • Docker и Docker Compose
  • Файл с cookies Instagram (instagram_cookies.txt в папке instagram-downloader/)

Быстрый старт

1. Настройка cookies

Перед запуском сервиса нужно положить instagram_cookies.txt в папку instagram-downloader/.

Куки экспортируются вручную из браузера расширением для cookies.txt — пошаговая процедура в cookies/README.md. Скрипты автоматического экспорта через yt-dlp --cookies-from-browser убраны: этот способ ломает сессию, куки после него быстро протухают.

2. Запуск сервиса

Вариант 1: Через корневой docker-compose (рекомендуется)

cd ..  # вернуться в корень проекта
docker compose up -d instagram-downloader

Вариант 2: Отдельно

docker compose up -d

3. Проверка работы

# Проверка здоровья сервиса
curl http://localhost:5556/health

# Должен вернуть: {"status":"ok","service":"instagram-downloader"}

API Endpoints

GET /health

Проверка здоровья сервиса.

Ответ:

{
  "status": "ok",
  "service": "instagram-downloader"
}

POST /cookies/check

Проверка, работают ли cookies прямо сейчас: делает лёгкий extract_info (без скачивания) по публичному тестовому ролику. Используется фоновым мониторингом в bot.py.

Ответ:

{
  "cookies_present": true,
  "cookies_valid": false,
  "detail": "текст ошибки от yt-dlp"
}

cookies_valid: null означает, что файл с куками не найден. Тестовый URL переопределяется переменной INSTAGRAM_COOKIE_TEST_URL.

POST /download/stream

Скачивание видео с Instagram.

Запрос:

{
  "url": "https://www.instagram.com/p/..."
}

Ответ:

  • Успех: бинарные данные видео (Content-Type: video/mp4)
  • Ошибка: JSON с описанием ошибки

Порты

  • Внешний порт: 5556
  • Внутренний порт контейнера: 5000

Обновление cookies

Ключевые куки Instagram живут около года, поэтому обновлять их по расписанию не нужно. Триггер на обновление — алерт 🍪⚠️ ПРОАКТИВНАЯ ПРОВЕРКА COOKIES из админ-бота (за состоянием следит фоновая проверка в bot.py, которая раз в 30 минут дёргает POST /cookies/check).

Процедура экспорта и доставки — в cookies/README.md. Перезапускать сервис после обновления не нужно: yt-dlp читает файл с диска при каждом запросе.

Troubleshooting

Сервис не может скачать видео

  1. Проверьте состояние куков: curl -s -X POST localhost:5556/cookies/check
  2. Проверьте наличие файла instagram_cookies.txt в папке instagram-downloader/ и что в нём есть sessionid
  3. Если cookies_valid: false — обновите куки по инструкции в cookies/README.md
  4. Проверьте логи: docker compose logs instagram-downloader

Cookies есть и не истекли по сроку, но всё равно login required

Instagram умеет блокировать сессию на своей стороне — тогда в логах видно Main webpage is locked behind the login page при формально валидном sessionid. Лечится только повторным экспортом куков. Провоцирует такую блокировку активная автоматическая работа с аккаунтом (например, постоянно открытая вкладка Instagram, непрерывно ходящая в сеть), поэтому после экспорта браузер лучше закрывать.

Структура файлов

instagram-downloader/
├── app.py                          # Основной код сервиса
├── Dockerfile                      # Образ Docker
├── docker-compose.yml              # Конфигурация для отдельного запуска
├── requirements.txt               # Python зависимости
├── INSTAGRAM_COOKIES_INSTRUCTIONS.md  # Отсылка к cookies/README.md
└── README.md                       # Этот файл