API de transcription YouTube en Python : 10 lignes avec requests

youtube_transcript_api._errors.IpBlocked:
Could not retrieve a transcript for the video.
YouTube is blocking requests from your IP.
Si ce traceback vous a amené ici, bienvenue. C'est le mode de défaillance standard du célèbre paquet pip dès que votre code quitte votre ordinateur portable et atterrit sur AWS, GCP ou n'importe quelle autre IP de datacenter. Cet article montre l'autre voie : une API de transcription YouTube hébergée que vous appelez depuis Python avec rien d'autre que requests. À la fin, vous aurez un script de dix lignes qui transforme n'importe quelle URL YouTube en texte de transcription, plus des branches propres pour les limites de débit et les vidéos sans sous-titres.
Pourquoi la bibliothèque pip meurt en production
youtube-transcript-api scrape YouTube directement depuis la machine qui l'exécute. En local, ça va. Déployez-le, et la détection de bots de YouTube signale la plage d'IP de votre fournisseur cloud en quelques jours, parfois en quelques minutes. J'ai détaillé tout cela dans pourquoi l'API de transcription YouTube se fait bloquer — en résumé : vous finissez par louer des proxies résidentiels pour lire des sous-titres publics, ce qui est absurde.
youtube2text.org gère la partie face à YouTube côté serveur. Votre code fait un appel HTTPS et reçoit du JSON.
Les dix lignes
Aucun compte nécessaire pour essayer — il existe un endpoint de clé de démonstration :
import requests
API = "https://youtube2text.org/api/transcribe"
KEY = requests.get("https://youtube2text.org/api/demo-key").json()["apiKey"]
resp = requests.get(API, params={"url": "https://youtu.be/dQw4w9WgXcQ"},
headers={"x-api-key": KEY}, timeout=60)
resp.raise_for_status()
result = resp.json()["result"]
print(result["title"])
print(result["content"][:300])
Le paramètre url accepte toutes les formes d'URL YouTube — watch?v=, youtu.be, shorts, embeds — ou simplement l'identifiant de vidéo à 11 caractères. La réponse vous donne videoId, title, pubDate, content, contentSize et un indicateur truncated.
Une réserve sur cette clé de démonstration : elle est partagée entre tout le monde et plafonnée à 5 vidéos par mois et par IP. Parfait pour un premier essai, inutilisable pour quoi que ce soit de sérieux.
Gérer les 429 et 404 comme un adulte
raise_for_status() convient pour une démo, mais les erreurs reviennent en JSON structuré avec un code sur lequel brancher :
import time
resp = requests.get(API, params={"url": video_url},
headers={"x-api-key": KEY}, timeout=60)
body = resp.json()
if resp.status_code == 200:
transcript = body["result"]["content"]
elif resp.status_code == 429:
time.sleep(body["error"]["retryAfterSeconds"]) # then retry
elif resp.status_code == 404:
if body["error"]["code"] == "TRANSCRIPT_UNAVAILABLE":
transcript = None # video exists, but has no captions — skip it
else:
raise ValueError(f"No such video: {video_url}") # VIDEO_NOT_FOUND
else:
raise RuntimeError(body["error"]["message"])
TRANSCRIPT_UNAVAILABLE mérite un moment d'honnêteté : les transcriptions proviennent des pistes de sous-titres de YouTube (manuelles ou générées automatiquement), et certaines vidéos n'en ont tout simplement pas. Aucune API ne peut faire apparaître un texte qui n'existe pas — pour celles-là, il faut de la vraie reconnaissance vocale, que j'ai comparée dans Whisper ou sous-titres YouTube. Réessayer ne servira à rien, donc abstenez-vous.
maxChars et budgets de tokens des LLM
Si la transcription est destinée à un prompt, la taille vous concerne. La transcription d'un podcast de trois heures avalera allègrement 100k tokens. Le paramètre maxChars plafonne la sortie — la valeur par défaut et le maximum sont tous deux 150000 :
resp = requests.get(API,
params={"url": video_url, "maxChars": 20000},
headers={"x-api-key": KEY}, timeout=60)
Avec la règle approximative des 4 caractères par token, maxChars=20000 donne environ 5k tokens. Vérifiez result["truncated"] pour savoir si vous avez tout reçu. Si vous branchez cela dans un pipeline de récupération plutôt qu'un simple prompt, l'article sur l'intégration LangChain couvre le découpage comme il faut.
Quitter la clé de démonstration
Quand 5 vidéos partagées par mois ne suffisent plus, connectez-vous avec Google sur youtube2text.org/app/keys et générez votre propre clé — sans numéro de téléphone, sans carte bancaire. Le niveau gratuit offre 5 vidéos par mois et par clé ; les formules payantes commencent à 5,99 $ pour 50. Les dix lignes ci-dessus ne changent pas, seule la chaîne dans l'en-tête change.