// ==UserScript== // @name Pornhub video download with one click // @name:ar Pornhub Video Download بنقرة واحدة // @name:bg Pornhub видео Изтеглете с едно щракване // @name:cs PornHub Video Stáhnout s jedním kliknutím // @name:da Pornhub video download med et enkelt klik // @name:de Pornhub Video Download mit einem Klick // @name:el Λήψη βίντεο pornhub με ένα κλικ // @name:en Pornhub video download with one click // @name:eo Pornhub Video Elŝuti per unu klako // @name:es Descarga de video pornhub con un solo clic // @name:fi Pornhub -videon lataa yhdellä napsautuksella // @name:fr Téléchargement vidéo pornhub en un clic // @name:fr-CA Téléchargement vidéo pornhub en un clic // @name:he הורדת וידאו של Pornhub בלחיצה אחת // @name:hr PornHub video preuzmi s jednim klikom // @name:hu Pornhub videó letöltése egy kattintással // @name:id Unduh video pornhub dengan satu klik // @name:it Download video di Pornhub con un clic // @name:ja ポルノハブビデオダウンロードワンクリックでダウンロードします // @name:ka Pornhub Video ჩამოტვირთვა ერთი დაჭერით // @name:ko 한 번의 클릭으로 Pornhub 비디오 다운로드 // @name:nb Pornhub video nedlasting med ett klikk // @name:nl Pornhub video downloaden met één klik // @name:pl Pobierz wideo Pornhub za pomocą jednego kliknięcia // @name:pt-BR Download de vídeo pornHub com um clique // @name:ro Descărcare video PornHub cu un singur clic // @name:ru Скачать видео Pornhub с одним щелчком // @name:sk Stiahnutie videa pornhub s jedným kliknutím // @name:sr ПорнХуб Видео Довнлоад са једним кликом // @name:sv Pornhub video nedladdning med ett klick // @name:th ดาวน์โหลดวิดีโอ Pornhub ด้วยคลิกเดียว // @name:tr Pornhub Video İndir Bir Tıkla İndir // @name:ug Pornhub سىن چۈشۈرۈش بىر چېكىش ئارقىلىق // @name:uk Завантажити відео Pornhub одним клацанням // @name:vi Tải xuống video pornhub chỉ bằng một cú nhấp chuột // @name:zh Pornhub 视频一键下载 // @name:zh-CN Pornhub 视频一键下载 // @name:zh-HK Pornhub 視頻一鍵下載 // @name:zh-SG Pornhub 视频一键下载 // @name:zh-TW Pornhub 視頻一鍵下載 // @description Pornhub video download with one click | pornhub.com | Download directly without login | Download free to watch paid videos | Download videos that are prohibited | Download all viewable resolutions // @description:ar Pornhub تنزيل مع نقرة واحدة // @description:bg Pornhub Video с едно щракване | // @description:cs Stahování videa PornHub | // @description:da Pornhub -video Download med et klik | // @description:de Pornhub -Video Download mit einem Klick | Pornhub.com | // @description:el Pornhub Video Download με ένα κλικ | Pornhub.com | // @description:en Pornhub video download with one click | pornhub.com | Download directly without login | Download free to watch paid videos | Download videos that are prohibited | Download all viewable resolutions // @description:eo Pornhub Video Elŝuti kun unu klako | Pornhub.com | // @description:es Pornhub Video Descarga con un clic | // @description:fi PornHub -video // @description:fr Téléchargement de la vidéo PornHub en un clic | Pornhub.com | // @description:fr-CA Téléchargement de la vidéo PornHub en un clic | Pornhub.com | // @description:he הורדת וידאו של Pornhub עם לחיצה אחת | // @description:hr Porno preuzimanje s jednim klikom | // @description:hu Pornhub videó egy kattintással | // @description:id Unduh video pornhub dengan satu klik | // @description:it Download video di Pornhub con un clic | // @description:ja Pornhubのダウンロード| // @description:ka Pornhub ვიდეო ჩამოტვირთვა ერთი დაჭერით | // @description:ko Pornhub는 한 번의 클릭으로 다운로드하십시오 // @description:nb Pornhub Video nedlasting med ett klikk | // @description:nl Pornhub -video downloaden met één klik | Pornhub.com | Download direct zonder inloggen | // @description:pl Pornhub Pobierz z jednym kliknięciem | // @description:pt-BR Download de vídeo porn, com um clique | // @description:ro Pornhub Descărcare cu un singur clic | // @description:ru Pornhub Video Скачать с одним кликом | // @description:sk Stiahnutie videa s jedným kliknutím // @description:sr ПорнХуб Видео Довнлоад са једним кликом | ПорнХуб.цом | Преузмите директно без пријаве | Преузмите бесплатни за гледање плаћених видео записа | Преузмите видео забрањене видео снимке | Преузмите све видљиве резолуције // @description:sv Pornhub Video Ladda ner med ett klick | // @description:th ดาวน์โหลดวิดีโอ Pornhub ด้วยการคลิกหนึ่งครั้ง | // @description:tr Pornhub bir tıklama ile indirin | // @description:ug PornHub سىن يوللاش بىر چېكىش ئارقىلىق چۈشۈرۈش | PornHub.com | بىۋاسىتە كىرىش | ھەقسىز سىنلارنى كۆرۈش ئۈچۈن ھەقسىز چۈشۈرۈڭ | چەكلەنگەن بارلىق كۆرگەزمە قىلىش // @description:uk Відео PornHub одним натисніть // @description:vi Tải xuống Video của Pornhub với một lần nhấp chuột | // @description:zh Pornhub 视频一键下载 | pornhub.com | 无需登录直接下载 | 可直接下载免费观看付费下载视频 | 可下载已禁止下载的视频 | 可下载所有可观看分辨率 // @description:zh-CN Pornhub 视频一键下载 | pornhub.com | 无需登录直接下载 | 可直接下载免费观看付费下载视频 | 可下载已禁止下载的视频 | 可下载所有可观看分辨率 // @description:zh-HK Pornhub 視頻一鍵下載 | pornhub.com | 無需登錄直接下載 | 可直接下載免費觀看付費下載視頻 | 可下載已禁止下載的視頻 | 可下載所有可觀看分辨率 // @description:zh-SG Pornhub 视频一键下载 | pornhub.com | 无需登录直接下载 | 可直接下载免费观看付费下载视频 | 可下载已禁止下载的视频 | 可下载所有可观看分辨率 // @description:zh-TW Pornhub 視頻一鍵下載 | pornhub.com | 無需登錄直接下載 | 可直接下載免費觀看付費下載視頻 | 可下載已禁止下載的視頻 | 可下載所有可觀看分辨率 // @grant unsafeWindow // @grant GM_setClipboard // @grant GM_download // @grant GM_addStyle // @match *://*.pornhub.com/view_video.php?viewkey=* // @match *://*.pornhubpremium.com/view_video.php?viewkey=* // @require https://update.greasyfork.org/scripts/498897/1404834/Toastnew.js // @author liuwanlin,heckles,MatthewXY,人民的勤务员 // @namespace https://github.com/ChinaGodMan/UserScripts // @supportURL https://github.com/ChinaGodMan/UserScripts/issues // @homepageURL https://github.com/ChinaGodMan/UserScripts // @homepage https://github.com/ChinaGodMan/UserScripts // @license MIT // @icon data:image/svg+xml;charset=utf-8;base64,Cjxzdmcgd2lkdGg9IjE5OCIgaGVpZ2h0PSI3MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjE5OCIgaGVpZ2h0PSI3MCIvPgo8cmVjdCB4PSIxMDgiIHk9IjEwIiB3aWR0aD0iODAiIGhlaWdodD0iNTAiIHJ4PSI0IiBmaWxsPSIjZjc5NzFkIi8+Cgo8ZyB0cmFuc2Zvcm09Im1hdHJpeCguMSAwIDAgLjEgODYuODUgMzAuMTUpIiBzdHJva2Utd2lkdGg9IjEwIj4KPHBhdGggZD0ibTg4Ny0zMGMtNS0yLTExLTMtMTctMy0yNC0yLTU0IDctNjggMTlsMy05N2gtNTd2MzAxaDUzdi0xN2MyNSAxNCA0MyAyMSA2NiAyMSA2Ni01IDkzLTY0IDkzLTExNi0xLTUyLTIzLTk3LTczLTEwOHptLTMyIDE3OWMtMzUgMC01MC00MS01MC03M3MxMS02NSA0OC02NSA0OCA0MSA0OCA3MGMwIDMyLTExIDY4LTQ2IDY4em0tMjAwLTg1YzAgMzEtMiA1MC01IDU4LTggMTgtMjQgMjgtNDIgMjktMTgtMS0yNi0xMC0zMy0yMy0yLTctMy0yNi0zLTU2di0xMDBoLTU4djEzOGMtMSA0OSAyNSA4NCA3MyA4NCAyNiAwIDU0LTkgNzItMjh2MjNoNTN2LTIxN2gtNTd6bS0yNDEtOTdjLTI4LTEtNTkgNi03NCAyMHYtOThoLTU3djMwMGg1N3YtMTA5YzAtMTggMi0zMiA1LTQxIDktMTggMjQtMjggNDMtMjggMTYgMCAyNSA4IDMyIDIwIDIgNiAzIDIxIDMgNDR2MTE1aDU4di0xMjhjMC0yMC0xLTM0LTMtNDMtMTItMzQtMzYtNTEtNjQtNTIiLz4KPHBhdGggZD0ibTY4LTQ1Yy0yNC0xLTYzIDgtNzUgMjd2LTIyaC01NnYyMjloNjB2LTEwM2MwLTI2IDItNDMgNS01MyA4LTIwIDI2LTMxIDQ1LTMxIDE4IDAgMjcgOSAzNCAyMyAyIDcgNCAyMyA0IDQ4djExNmg2MHYtMTQyYzAtMTgtMS0zMS0zLTQxLTEwLTM1LTQxLTUwLTc0LTUxem0tMjU3IDI3di0yMmgtNTZ2MjI5aDYwdi03MGMwLTM5IDItNjUgNS03NyA0LTEyIDgtMjEgMTQtMjYgNi00IDEzLTcgMjItNyA4IDAgMTggNCAyOCAxMGwxOS01MmMtMTMtOC0yNi0xMi00MC0xMi0yMCAxLTQwIDEyLTUyIDI3em0tMjA1LTI3Yy0yMiAwLTQyIDUtNjAgMTUtMTkgMTAtMzMgMjQtNDMgNDNzLTE1IDM4LTE1IDU5YzAgMjYgNSA0OCAxNSA2NiAxMCAxOSAyNSAzMyA0NCA0MiAxOSAxMCAzOSAxNCA2MCAxNCAzNCAwIDYyLTExIDg0LTM0IDIzLTIzIDM0LTUxIDM0LTg2IDAtMzQtMTEtNjMtMzMtODUtMjMtMjMtNTEtMzQtODYtMzRtNDAgMTcyYy0xMCAxMi0yNCAxOC0zOSAxOC0xNiAwLTI5LTYtNDAtMThzLTE2LTMwLTE2LTUyYzAtMjMgNS00MCAxNi01MnMyNC0xOCA0MC0xOGMxNSAwIDI5IDYgMzkgMTggMTEgMTIgMTYgMjkgMTYgNTEgMCAyMy01IDQxLTE2IDUzbS0zMTAtMjU0aC0xMDN2MzE2aDY0di0xMTloNDJjNTEgMiAxMDItNiAxMjYtNTEgNy0xMyAxMC0yOSAxMC00OSAwLTQzLTI0LTgxLTYzLTkyLTEyLTMtMzctNS03Ni01em00NyAxMzhjLTkgNC0yNiA1LTUxIDVoLTM1di04OWgzMWMyMyAwIDM4IDAgNDYgMiAyMiA1IDM2IDIyIDM2IDQyLTEgMTktMTEgMzQtMjcgNDAiIGZpbGw9IiNmZmYiLz4KPC9nPgo8L3N2Zz4K // @compatible chrome // @compatible firefox // @compatible edge // @compatible opera // @compatible safari // @compatible kiwi // @version 2026.3.31.1 // @created 2025-03-05 01:45:13 // @modified 2025-03-05 01:45:13 // ==/UserScript== //!人民的勤务员修改自以下脚本 感谢heckles和liuwanlin /*https://greasyfork.org/zh-CN/scripts/491333 https://greasyfork.org/zh-CN/scripts/491329 https://greasyfork.org/zh-CN/scripts/551131 */ (function () { 'use strict' const userLang = (navigator.languages && navigator.languages[0]) || navigator.language || 'en' const translations = { 'en': { downloading: 'Downloading...', finderror: 'Video download link not found', fetcherror: 'Error fetching video, please check the console for details', downloadsuccess: 'Download successful', downloaderror: 'Error downloading video, please check the console for details', downloadfailed: 'Download failed', downloadfailed_nosize: 'Unable to retrieve file size', copydownloadbtn: 'Copy', copysuccess: 'Copy successful', downloadbtn: 'Download', linkTip: 'Video download URL:' }, 'zh-CN,zh,zh-SG': { downloading: '下载中...', finderror: '未找到视频下载链接', fetcherror: '获取视频时出错,请到控制台查看详细信息', downloadsuccess: '下载成功', downloaderror: '下载视频时出错,请到控制台查看详细信息', downloadfailed: '下载失败', downloadfailed_nosize: '无法获取文件大小', copydownloadbtn: '复制', copysuccess: '复制成功', downloadbtn: '下载', linkTip: '视频下载地址:' }, 'zh-TW,zh-HK,zh-MO': { downloading: '下載中...', finderror: '未找到視頻下載連結', fetcherror: '獲取視頻時出錯,請到控制台查看詳細信息', downloadsuccess: '下載成功', downloaderror: '下載視頻時出錯,請到控制台查看詳細信息', downloadfailed: '下載失敗', downloadfailed_nosize: '無法獲取文件大小', copydownloadbtn: '複製', copysuccess: '複製成功', downloadbtn: '下載', linkTip: '視頻下載地址:' }, 'ja': { downloading: 'ダウンロード中...', finderror: 'ビデオのダウンロードリンクが見つかりません', fetcherror: 'ビデオの取得中にエラーが発生しました。詳細はコンソールを確認してください', downloadsuccess: 'ダウンロード成功', downloaderror: 'ビデオのダウンロード中にエラーが発生しました。詳細はコンソールを確認してください', downloadfailed: 'ダウンロード失敗', downloadfailed_nosize: 'ファイルサイズを取得できません', copydownloadbtn: 'アドレスをコピー', copysuccess: 'コピー成功', downloadbtn: 'ビデオをダウンロード', linkTip: 'ビデオダウンロードURL:' }, 'vi': { downloading: 'Đang tải xuống...', finderror: 'Không tìm thấy liên kết tải video', fetcherror: 'Lỗi khi tải video, vui lòng kiểm tra bảng điều khiển để biết chi tiết', downloadsuccess: 'Tải xuống thành công', downloaderror: 'Lỗi khi tải video, vui lòng kiểm tra bảng điều khiển để biết chi tiết', downloadfailed: 'Tải xuống thất bại', downloadfailed_nosize: 'Không thể lấy kích thước tệp', copydownloadbtn: 'Sao chép địa chỉ', copysuccess: 'Sao chép thành công', downloadbtn: 'Tải xuống video', linkTip: 'URL tải video:' }, 'fr': { downloading: 'Téléchargement...', finderror: 'Lien de téléchargement vidéo introuvable', fetcherror: 'Erreur lors de la récupération de la vidéo, veuillez vérifier la console pour plus de détails', downloadsuccess: 'Téléchargement réussi', downloaderror: 'Erreur lors du téléchargement de la vidéo, veuillez vérifier la console pour plus de détails', downloadfailed: 'Échec du téléchargement', downloadfailed_nosize: 'Impossible de récupérer la taille du fichier', copydownloadbtn: 'Copier l’adresse', copysuccess: 'Copie réussie', downloadbtn: 'Télécharger la vidéo', linkTip: 'URL de téléchargement vidéo :' }, 'es': { downloading: 'Descargando...', finderror: 'No se encontró el enlace de descarga del video', fetcherror: 'Error al obtener el video, consulte la consola para más detalles', downloadsuccess: 'Descarga exitosa', downloaderror: 'Error al descargar el video, consulte la consola para más detalles', downloadfailed: 'Error en la descarga', downloadfailed_nosize: 'No se puede obtener el tamaño del archivo', copydownloadbtn: 'Copiar dirección', copysuccess: 'Copia exitosa', downloadbtn: 'Descargar video', linkTip: 'URL de descarga del video:' } } const getTranslations = (lang) => { for (const key in translations) { if (key === lang || key.split(',').includes(lang)) { return translations[key] } } return translations['en'] } const translate = new Proxy( function (key) { const lang = userLang const strings = getTranslations(lang) return strings[key] || translations['en'][key] }, { get(target, prop) { const lang = userLang const strings = getTranslations(lang) return strings[prop] || translations['en'][prop] } } ) unsafeWindow.translate = translate const MutationObserver = unsafeWindow.MutationObserver || unsafeWindow.WebKitMutationObserver || unsafeWindow.MozMutationObserver const mutationObserver = new MutationObserver(mutations => { mutationObserver.disconnect() setTimeout(() => { unsafeWindow.VideoParsing.init() }, 200) }) class VideoParsing { static addStyle() { GM_addStyle(` .download-urls { margin: 15px 0px; padding: 12px; background: #000; border: 1px solid #6f6f6f; border-radius: 5px; font-size: 14px; max-width: 600px; } .download-urls h3 { margin-bottom: 8px; font-size: 16px; font-weight: bold; color: #333; } .download-urls ul { padding: 0; margin: 0; list-style: none; } .download-urls ul li { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; } .download-url-label { flex: 0 0 90px; font-weight: bold; color: #FFF; } .download-url-input { flex: 1; font-size: 12px; padding: 3px 6px; border: 1px solid #ccc; border-radius: 5px; background: #fff; color: #000; } .download-url-copy, .download-url-mp4 { padding: 4px 10px; border-radius: 5px; border: none; cursor: pointer; font-size: 12px; } .download-url-copy { background: #eee; color: #333; } .download-url-mp4 { background: #ff9000; color: #fff; } .download-url-copy:hover { background: #ddd; } `) } // 根据 key 开头字母获取对象中的值,返回数组 static getObjectValueByStartsWithChar(obj, char) { const vars = [] Object.keys(obj).forEach(key => { if (key.startsWith(char)) { vars.push({ key: key, value: obj[key] }) } }) return vars } // 获取下载地址信息,返回数组 static getUrlInfo() { const flashvars = this.getObjectValueByStartsWithChar(unsafeWindow, 'flashvars_') if (!flashvars.length) { Toast(translate('fetcherror'), 3000, 'rgb(219, 18, 35)', '#ffffff', 'top') console.warn(translate.finderror) return } let videosInfo = [] try { videosInfo = flashvars[0]['value']['mediaDefinitions'] } catch (e) { Toast(translate('fetcherror'), 3000, 'rgb(219, 18, 35)', '#ffffff', 'top') console.error(translate.fetcherror, e) return } let remoteAddress let urlInfo = [] for (let i = 0; i < videosInfo.length; i++) { if (videosInfo[i]['remote']) { remoteAddress = videosInfo[i]['videoUrl'] break } } if (remoteAddress) { const xhr = new XMLHttpRequest() xhr.open('GET', remoteAddress, false) xhr.onload = function () { if (xhr.status === 200) { try { const data = JSON.parse(xhr.responseText) if (Array.isArray(data)) { urlInfo = urlInfo.concat(data.map(item => ({ quality: item.quality + '.' + item.format, url: item.videoUrl }))) } } catch (err) { console.error(err) } } } xhr.send() } return urlInfo } // 注入到下载面板 static injectUrls2Dom(urlInfo) { const container = document.createElement('div') container.className = 'download-urls' const title = document.createElement('h3') title.textContent = translate.linkTip container.appendChild(title) if (urlInfo && urlInfo.length > 0) { const ul = document.createElement('ul') urlInfo.forEach(item => { const li = document.createElement('li') const label = document.createElement('span') label.className = 'download-url-label' label.textContent = `[ ${item.quality} ]` const input = document.createElement('input') input.className = 'download-url-input' input.value = item.url input.readOnly = true const copyBtn = document.createElement('button') copyBtn.className = 'download-url-copy' copyBtn.textContent = translate.copydownloadbtn copyBtn.dataset.href = item.url const dlBtn = document.createElement('button') dlBtn.className = 'download-url-mp4' dlBtn.textContent = translate.downloadbtn dlBtn.dataset.href = item.url li.appendChild(label) li.appendChild(input) li.appendChild(copyBtn) li.appendChild(dlBtn) ul.appendChild(li) }) container.appendChild(ul) } const player = document.querySelector('#player') if (player) { player.insertAdjacentElement('afterend', container) } const playerWrapper = document.querySelector('.playerWrapper') if (playerWrapper) { playerWrapper.insertAdjacentElement('afterend', container) } } // 初始化事件 static initEvens() { document.addEventListener('click', function (e) { if (e.target.classList.contains('download-url-copy')) { e.preventDefault() const url = e.target.dataset.href GM_setClipboard(url) Toast(translate.copysuccess, 3000, 'rgb(18, 219, 18)', '#ffffff', 'top') } }) } static initDownEvens() { document.addEventListener('click', function (e) { if (e.target.classList.contains('download-url-mp4')) { e.preventDefault() downloadMp4(e.target.dataset.href, e.target) } }) } static init() { this.addStyle() this.injectUrls2Dom(this.getUrlInfo()) this.initEvens() this.initDownEvens() } } unsafeWindow.VideoParsing = VideoParsing //转换字节 function getHumanReadableSize(sizeb) { const sizes = ['B', 'KB', 'MB', 'GB', 'TB'] const size = sizeb let i = parseInt(Math.floor(Math.log(size) / Math.log(1024))) const humanReadableSize = (size / Math.pow(1024, i)).toFixed(1) + ' ' + sizes[i] return humanReadableSize } function sanitizeTitle() { var title = document.title title = title.replace(/- Pornhub\.com/, '') return title.replace(/[/:*?"<>|]/g, '_').trim() } //下载函数 async function downloadMp4(videoUrl, element) { try { const response = await fetch(videoUrl) if (!response.ok) { element.textContent = translate('downloadfailed') } const contentLength = response.headers.get('Content-Length') if (!contentLength) { element.textContent = translate('downloadfailed_nosize') return } const reader = response.body.getReader() const totalSize = contentLength ? parseInt(contentLength, 10) : 0 let downloadedSize = 0 const chunks = [] while (true) { const { done, value } = await reader.read() if (done) break downloadedSize += value.length chunks.push(value) if (totalSize) { const progress = ((downloadedSize / totalSize) * 100).toFixed(2) element.textContent = `${translate('downloading')} ${progress}% (${getHumanReadableSize(downloadedSize)} / ${getHumanReadableSize(totalSize)})` } else { element.textContent = `${translate('downloading')} ${getHumanReadableSize(downloadedSize)}` } } const blob = new Blob(chunks) const url = window.URL.createObjectURL(blob) const a = document.createElement('a') a.style.display = 'none' a.href = url a.download = sanitizeTitle() + '.mp4' document.body.appendChild(a) a.click() window.URL.revokeObjectURL(url) document.body.removeChild(a) Toast(translate('downloadsuccess'), 3000, 'rgb(18, 219, 18)', '#ffffff', 'top') } catch (error) { Toast(translate('downloaderror'), 3000, 'rgb(173, 7, 7)', '#ffffff', 'top') console.error(translate('downloaderror'), error) } } VideoParsing.init() })()