saveapi.org

yt-dlp и Instagram: «login required», пустой результат и чем заменить

yt-dlp — отличный инструмент, а Instagram — сайт, с которым он справляется хуже всего, и не по своей вине: Instagram отдаёт страницы за стеной логина всему, что не похоже на залогиненный браузер, а серверный IP не похож никогда. Это руководство объясняет, что означает ошибка, почему привычные решения деградируют и как та же ссылка выглядит через API скачивания — измерено, а не заявлено.

Обновлено

Что на самом деле говорит ошибка

Сообщение сваливает три разные ситуации в одну строку: пост недоступен, ваш IP упёрся в лимит или Instagram хочет сессию. На адресе дата-центра это почти всегда третье — запрос не доходит до поста, он сначала упирается в стену логина. yt-dlp снаружи не может их различить, поэтому его совет — «попробуйте cookie».

Terminal
$ yt-dlp https://www.instagram.com/reel/ABC123/
ERROR: [Instagram] ABC123: Requested content is not available,
rate-limit reached or login required. Use --cookies,
--cookies-from-browser, --username and --password, or --netrc

Почему cookie помогают лишь на время

Экспорт сессии браузера работает в тот же день и перестаёт через несколько дней: Instagram ротирует токены сессии, привязывает их к IP и устройству, с которых они пришли, и помечает аккаунты, тянущие сотни постов с сервера. Решение превращается в ротацию аккаунтов и прокси, которой надо управлять, — это скрейпинг-операция, а не команда скачивания.

Что мы измерили с серверного IP

Перед тем как убрать yt-dlp из собственного пайплайна, мы прогнали через него 13 публичных reels с адреса Hetzner: 0 успешных, отдельные вызовы тянулись до 45 секунд перед падением. Собственный embed-эндпоинт Instagram не лучше — 0 из 11. Ссылки были в порядке; домашнее подключение их разрешило. Дело в адресе, а не в инструменте.

Та же ссылка через API

Один GET, никаких cookie с вашей стороны, никакого браузера. Разрешение происходит в цепочке источников, не зависящих от сессии Instagram, а ответ имеет одну форму для reel, поста, карусели и истории. Медианное время ответа измеряется вживую и показано на главной странице.

Terminal
curl -s "https://api.saveapi.org/v1/instagram" \
  -H "Authorization: Bearer sk_live_xxxx" \
  -G --data-urlencode "url=https://www.instagram.com/reel/ABC123/"

Прямая замена в Python

Если ваш код вызывал yt-dlp ради URL, а файл скачивал сам, это тот же контракт: передаёте ссылку, получаете прямые URL медиа, забираете байты с CDN. Что вы теряете — выбор формата yt-dlp; в ответе на каждое медиа Instagram приходит один вариант, так что выбирать нечего.

Python
import httpx

def resolve(link: str) -> list[str]:
    """yt-dlp o'rniga: havoladan to'g'ridan-to'g'ri media URL'lar."""
    r = httpx.get(
        "https://api.saveapi.org/v1/download",
        params={"url": link},
        headers={"Authorization": "Bearer sk_live_xxxx"},
        timeout=30,
    )
    data = r.json()
    if not data["success"]:
        raise RuntimeError(data["error"]["code"])
    return [m["url"] for m in data["medias"]]

Вопросы перед началом

yt-dlp вообще ещё качает Instagram?
С домашнего подключения и свежими cookie — часто да. С сервера, по нашему измерению, — нет, а для бота или бэкенда важен именно серверный случай.
API использует мой аккаунт Instagram?
Нет. Нет логина, нет cookie, ваш аккаунт не участвует; запрос — только ссылка и ваш API-ключ.
Сколько стоит неудачная ссылка?
Ссылка, которую отверг сам Instagram — закрытая или удалённая, — стоит 0.1 кредита и возвращается со стабильным кодом. Всё, что упало с нашей стороны, не стоит ничего, и ответ говорит, что именно произошло.

Платформы, использованные здесь

Другие руководства

Запустите это руководство со своим ключом

Ключ за минуту. 1 000 бесплатных кредитов, без карты и без срока.

Получить ключ и попробоватьПолный справочник API