{"record":{"id":"116138f6bfa69641","repo":"yt-dlp/yt-dlp","slug":"failed-to-decrypt-with-dpapi-see-https-github","errorCode":null,"errorMessage":"Failed to decrypt with DPAPI. See  https://github.com/yt-dlp/yt-dlp/issues/10927  for more info","messagePattern":"Failed to decrypt with DPAPI\\. See  https://github\\.com/yt-dlp/yt-dlp/issues/10927  for more info","errorType":"exception","errorClass":"DownloadError","httpStatus":null,"severity":"error","filePath":"yt_dlp/cookies.py","lineNumber":1101,"sourceCode":"        _fields_ = [('cbData', ctypes.wintypes.DWORD),\n                    ('pbData', ctypes.POINTER(ctypes.c_char))]\n\n    buffer = ctypes.create_string_buffer(ciphertext)\n    blob_in = DATA_BLOB(ctypes.sizeof(buffer), buffer)\n    blob_out = DATA_BLOB()\n    ret = ctypes.windll.crypt32.CryptUnprotectData(\n        ctypes.byref(blob_in),  # pDataIn\n        None,  # ppszDataDescr: human readable description of pDataIn\n        None,  # pOptionalEntropy: salt?\n        None,  # pvReserved: must be NULL\n        None,  # pPromptStruct: information about prompts to display\n        0,  # dwFlags\n        ctypes.byref(blob_out),  # pDataOut\n    )\n    if not ret:\n        message = 'Failed to decrypt with DPAPI. See  https://github.com/yt-dlp/yt-dlp/issues/10927  for more info'\n        logger.error(message)\n        raise DownloadError(message)  # force exit\n\n    result = ctypes.string_at(blob_out.pbData, blob_out.cbData)\n    ctypes.windll.kernel32.LocalFree(blob_out.pbData)\n    return result\n\n\ndef _config_home():\n    return os.environ.get('XDG_CONFIG_HOME', os.path.expanduser('~/.config'))\n\n\ndef _open_database_copy(database_path, tmpdir):\n    # cannot open sqlite databases if they are already in use (e.g. by the browser)\n    database_copy_path = os.path.join(tmpdir, 'temporary.sqlite')\n    shutil.copy(database_path, database_copy_path)\n    conn = sqlite3.connect(database_copy_path)\n    return conn.cursor()\n\n","sourceCodeStart":1083,"sourceCodeEnd":1119,"githubUrl":"https://github.com/yt-dlp/yt-dlp/blob/81ecd58b1394793e6da9998cc19fdb45657f1685/yt_dlp/cookies.py#L1083-L1119","documentation":"On Windows, Chromium cookie values whose encrypted blob has no v10/v11 prefix are decrypted with DPAPI via CryptUnprotectData. That API is bound to the Windows logon that encrypted the data; when it fails (ret == 0), yt-dlp logs the message referencing issue #10927 and raises DownloadError to force exit. Common root cause: cookies encrypted under a different Windows user/elevation context, or Chrome 127+ app-bound encryption which refuses to unprotect from other processes.","triggerScenarios":"--cookies-from-browser chrome/edge/brave/... on Windows where the 'other' prefixed cookies (DPAPI branch in _decrypt_windows_chromium) hit CryptUnprotectData failure. Typical: running yt-dlp elevated (as admin) while the cookie store belongs to the regular user; running under a service account; profile copied from another machine/user; Chrome 127+ app-bound (v20) cookies.","commonSituations":"User runs the terminal 'as Administrator' so DPAPI cannot access the interactive user's master key; scheduled-task/service context; domain profile roaming; cookies synced from another device with older encryption; new Chrome app-bound encryption on fully patched systems.","solutions":["Run yt-dlp from a normal (non-elevated) terminal as the same Windows user that owns the browser profile","Update yt-dlp to the latest nightly — handling around Chrome 127+ app-bound encryption (issue #10927) is actively improved","Close the browser, or use a different supported browser (firefox) whose cookie store does not need DPAPI","Durable workaround: export cookies to cookies.txt from the browser and pass --cookies cookies.txt"],"exampleFix":"# before (elevated PowerShell — DPAPI cannot see the user's key)\nStart-Process powershell -Verb RunAs; yt-dlp --cookies-from-browser chrome URL\n# after (normal terminal, same user as Chrome profile)\nyt-dlp --cookies-from-browser chrome URL","handlingStrategy":"fallback","validationCode":"# Windows: run yt-dlp in the same interactive, non-elevated context that owns the cookies\nimport ctypes, os\n\ndef dpapi_context_sane():\n    # heuristics: not elevated, not SYSTEM/service\n    try:\n        return not ctypes.windll.shell32.IsUserAnAdmin()\n    except Exception:\n        return False\n\nif os.name == 'nt' and not dpapi_context_sane():\n    raise SystemExit('Run without elevation as the browser user, or use --cookies cookies.txt')","typeGuard":null,"tryCatchPattern":"from yt_dlp.utils import DownloadError\ntry:\n    ydl.download([url])\nexcept DownloadError as e:\n    if 'DPAPI' in str(e):\n        # per-user Windows encryption mismatch — switch to exported cookies\n        opts.pop('cookiesfrombrowser', None); opts['cookiefile'] = 'cookies.txt'\n        with YoutubeDL(opts) as y2:\n            y2.download([url])\n    else:\n        raise","preventionTips":["Never extract Chromium cookies from an elevated/service context on Windows; use the interactive user session","Keep yt-dlp current — Chrome app-bound encryption (v20) support improves release to release","Ship a cookies.txt fallback in automation so DPAPI failures do not abort pipelines"],"tags":["windows","chrome","cookies","dpapi","decryption","download-error"],"backgroundTag":"dpapi-decryption-failed","analyzedSha":"81ecd58b1394793e6da9998cc19fdb45657f1685","analyzedAt":"2026-08-22T12:21:25.439Z","schemaVersion":2},"datasetVersion":"2026-08-22T14:17:55.899Z"}