{"record":{"id":"d45728cf84f23ceb","repo":"ytdl-org/youtube-dl","slug":"pornhub-said-s","errorCode":null,"errorMessage":"PornHub said: %s","messagePattern":"PornHub said: (.+?)","errorType":"exception","errorClass":"ExtractorError","httpStatus":null,"severity":"error","filePath":"youtube_dl/extractor/pornhub.py","lineNumber":284,"sourceCode":"        self._login(host)\n\n        self._set_cookie(host, 'age_verified', '1')\n\n        def dl_webpage(platform):\n            self._set_cookie(host, 'platform', platform)\n            return self._download_webpage(\n                'https://www.%s/view_video.php?viewkey=%s' % (host, video_id),\n                video_id, 'Downloading %s webpage' % platform)\n\n        webpage = dl_webpage('pc')\n\n        error_msg = self._html_search_regex(\n            (r'(?s)<div[^>]+class=([\"\\'])(?:(?!\\1).)*\\b(?:removed|userMessageSection)\\b(?:(?!\\1).)*\\1[^>]*>(?P<error>.+?)</div>',\n             r'(?s)<section[^>]+class=[\"\\']noVideo[\"\\'][^>]*>(?P<error>.+?)</section>'),\n            webpage, 'error message', default=None, group='error')\n        if error_msg:\n            error_msg = re.sub(r'\\s+', ' ', error_msg)\n            raise ExtractorError(\n                'PornHub said: %s' % error_msg,\n                expected=True, video_id=video_id)\n\n        if any(re.search(p, webpage) for p in (\n                r'class=[\"\\']geoBlocked[\"\\']',\n                r'>\\s*This content is unavailable in your country')):\n            self.raise_geo_restricted()\n\n        # video_title from flashvars contains whitespace instead of non-ASCII (see\n        # http://www.pornhub.com/view_video.php?viewkey=1331683002), not relying\n        # on that anymore.\n        title = self._html_search_meta(\n            'twitter:title', webpage, default=None) or self._html_search_regex(\n            (r'(?s)<h1[^>]+class=[\"\\']title[\"\\'][^>]*>(?P<title>.+?)</h1>',\n             r'<div[^>]+data-video-title=([\"\\'])(?P<title>(?:(?!\\1).)+)\\1',\n             r'shareTitle[\"\\']\\s*[=:]\\s*([\"\\'])(?P<title>(?:(?!\\1).)+)\\1'),\n            webpage, 'title', group='title')\n","sourceCodeStart":266,"sourceCodeEnd":302,"githubUrl":"https://github.com/ytdl-org/youtube-dl/blob/956b8c585591b401a543e409accb163eeaaa1193/youtube_dl/extractor/pornhub.py#L266-L302","documentation":"PornHubIE._real_extract raises ExtractorError('PornHub said: %s' % error_msg, expected=True) right after downloading the PC webpage, when the HTML contains an error block matched by either the 'removed|userMessageSection' div regex or the 'noVideo' section regex. The scraped block text (whitespace-collapsed) is appended, so the message is the site's own removal/unavailability notice.","triggerScenarios":"Extracting a video that was removed (removed div), deleted by its uploader, made private, or blocked, where the page renders a userMessageSection/noVideo block instead of the player; checked before geo-blocking detection, so plain removal hits this branch first.","commonSituations":"Stale links in saved playlists pointing to taken-down videos; DMCA removals; uploader-deleted content; age/verification gating that renders the same error section. Distinct from geo-blocking, which is detected just after this check and raises raise_geo_restricted instead.","solutions":["Read the trailing site message in the error — it states whether the video was removed or is otherwise unavailable.","Drop the dead URL from the batch and continue with remaining entries.","Confirm in a browser that the video still exists; if the browser shows it fine, update youtube-dl (markup drift can false-positive this regex).","If the page says deleted/removed, no client-side fix exists — obtain a re-uploaded or canonical URL."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    info = ydl.extract_info(url)\nexcept ExtractorError as e:\n    if 'PornHub said:' in str(e):\n        mark_dead(url)  # removed/private; skip permanently","preventionTips":["Classify 'PornHub said:' errors as permanent URL failures in job runners.","Distinguish this from geo-restriction (different exception path) before choosing a fix.","Re-validate stored PornHub links occasionally to purge takedowns."],"tags":["pornhub","content-removed","html-scraping","expected-error"],"backgroundTag":null,"analyzedSha":"956b8c585591b401a543e409accb163eeaaa1193","analyzedAt":"2026-08-14T18:59:47.863Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}