Captcha

The player response included a captcha view model.

The error#

When no formats are found and the playability status has errorScreen.playerCaptchaViewModel, yt-dlp appends this to the reason:

. YouTube is requiring a captcha challenge before playback

The reason YouTube already sent is kept in front of that sentence. The result goes to raise_no_formats with expected=True.

This is not the sign-in branch. Sign-in runs first, when sign in is in the reason. Captcha is the following branch.

What triggers it#

get_first(playability_statuses, ('errorScreen', 'playerCaptchaViewModel', {dict})) is truthy, and the sign-in branch did not already handle the reason.

How to confirm#

The exception or warning ends with YouTube is requiring a captcha challenge before playback. A page that only says sign in is the sign-in page, even if it feels like a bot check.

Fixes#

This version does not include a solver call in that branch. It reports the captcha and stops, unless ignore_no_formats_error or wait_for_video turns the error into a warning. Those flags do not complete the captcha. They only change the error into a warning so the rest of the metadata can be returned with no formats.

SocialScrape#

Video details are GET /v1/youtube/video. Transcripts are GET /v1/youtube/video/transcript: the video's own captions. A video with no captions returns transcript_unavailable and costs nothing. AI transcription of YouTube audio is not available yet.

Failed requests cost 0 credits. New accounts get 100 credits on signup, no card.

Questions

Will a cookie skip the captcha?

Only if YouTube stops sending playerCaptchaViewModel. The branch is that object, not the cookie jar.

Does SocialScrape ask the caller to solve a captcha?

No. A block on our fetch is upstream_blocked, which is free to retry.