ytdl-org/youtube-dl · error · ExtractorError
Udemy asks you to solve a CAPTCHA. Login with browser, solve
Error message
Udemy asks you to solve a CAPTCHA. Login with browser, solve CAPTCHA, then export cookies and pass cookie file to youtube-dl with --cookies.
What it means
Raised by UdemyIE._download_webpage_handle when the fetched page contains PerimeterX bot-protection markers ('Please verify you are a human', the automation-tools denial text, or the _pxCaptcha field). It tells the user to solve the CAPTCHA in a browser and reuse the session cookies. Expected error.
Source
Thrown at youtube_dl/extractor/udemy.py:143
error_data = error.get('data')
if error_data:
error_str += ' - %s' % error_data.get('formErrors')
raise ExtractorError(error_str, expected=True)
def _download_webpage_handle(self, *args, **kwargs):
headers = kwargs.get('headers', {}).copy()
headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36'
kwargs['headers'] = headers
ret = super(UdemyIE, self)._download_webpage_handle(
*args, **compat_kwargs(kwargs))
if not ret:
return ret
webpage, _ = ret
if any(p in webpage for p in (
'>Please verify you are a human',
'Access to this page has been denied because we believe you are using automation tools to browse the website',
'"_pxCaptcha"')):
raise ExtractorError(
'Udemy asks you to solve a CAPTCHA. Login with browser, '
'solve CAPTCHA, then export cookies and pass cookie file to '
'youtube-dl with --cookies.', expected=True)
return ret
def _download_json(self, url_or_request, *args, **kwargs):
headers = {
'X-Udemy-Snail-Case': 'true',
'X-Requested-With': 'XMLHttpRequest',
}
for cookie in self._downloader.cookiejar:
if cookie.name == 'client_id':
headers['X-Udemy-Client-Id'] = cookie.value
elif cookie.name == 'access_token':
headers['X-Udemy-Bearer-Token'] = cookie.value
headers['X-Udemy-Authorization'] = 'Bearer %s' % cookie.value
if isinstance(url_or_request, compat_urllib_request.Request):View on GitHub (pinned to 956b8c5855)
Solutions
- Log into Udemy in a normal browser, solve any CAPTCHA, export cookies, and pass --cookies udemy_cookies.txt.
- Slow down: add --sleep-interval/--max-sleep-interval and limit parallelism (--limit-rate, fewer concurrent jobs).
- Run from a residential IP rather than a datacenter/VPN egress.
- Retry later; PerimeterX blocks are often temporary once a clean session is established.
Defensive patterns
Strategy: fallback
Type guard
def px_blocked(page: str) -> bool:
return any(m in page for m in ('Please verify you are a human', '_pxCaptcha', 'automation tools')) Try / catch
try:
ydl.extract_info(url)
except ExtractorError as e:
if 'CAPTCHA' in str(e):
pause_and_switch_to_fresh_cookies() # solve in browser, re-export, resume
else:
raise Prevention
- Always pass fresh browser cookies (--cookies) for Udemy.
- Throttle with --sleep-interval and run from residential IPs; PerimeterX escalates with request volume.
- Solve the CAPTCHA once in a browser and reuse that session; do not retry blindly.
When it happens
Trigger: Any Udemy webpage download whose HTML contains one of the three PerimeterX markers — triggered by datacenter IPs, high request rates, a spoofed Chrome 72 User-Agent the site distrusts, or missing valid cookies.
Common situations: Batch-download scripts hammering udemy.com, running from cloud/VPN IPs, expired cookie jars, repeated login attempts.
Related errors
- YandexMusic has considered youtube-dl requests automated and
- Unable to login. Twitch said: %s
- Course %s is not free. You have to pay for it before you can
- %s
- 91 Porn says: Daily limit 10 videos exceeded
AI-assisted analysis of ytdl-org/youtube-dl@956b8c5855 (2026-08-14).
Data as JSON: /api/errors/b3a9d650eaba4112.
Report an issue: GitHub.