Python: How to use Chrome cookies in requests

Question:

I am searching for a method to get my cookies from my chrome browser (default), and use it using requests.

I have ofcourse already searched around, and found for example this; How to get cookies from web-browser with Python?
But that does not work anymore, because Chrome keeps on updating. And the modules they name in the answer were last tested in 2016.

So, the code they gave at the answer was + my extra stuff to get the cookies back

import win32crypt
import browsercookie
import requests

session = requests.Session()
cj = browsercookie.chrome()
r = session.get("https://stackoverflow.com/", cookies=cj)
print session.cookies.get_dict()

But when I run this (while being logged into stackoverflow on my browser), it return {}. And that’s not alot (not the result I was loking for)

Asked By: Aaron Jonk

||

Answers:

I have a good script to read Chrome cookies directly on /Default/Cookies. I think you would work fine.

import sqlite3
import sys
from os import getenv, path
import os
from Crypto.Cipher import AES
from Crypto.Protocol.KDF import PBKDF2
import keyring

def get_cookies(url, cookiesfile):

    def chrome_decrypt(encrypted_value, key=None):
        dec = AES.new(key, AES.MODE_CBC, IV=iv).decrypt(encrypted_value[3:])
        decrypted = dec[:-dec[-1]].decode('utf8')
        return decrypted

    cookies = []
    if sys.platform == 'win32':
        import win32crypt
        conn = sqlite3.connect(cookiesfile)
        cursor = conn.cursor()
        cursor.execute(
            'SELECT name, value, encrypted_value FROM cookies WHERE host_key == "' + url + '"')
        for name, value, encrypted_value in cursor.fetchall():
            if value or (encrypted_value[:3] == b'v10'):
                cookies.append((name, value))
            else:
                decrypted_value = win32crypt.CryptUnprotectData(
                    encrypted_value, None, None, None, 0)[1].decode('utf-8') or 'ERROR'
                cookies.append((name, decrypted_value))

    elif sys.platform == 'linux':
        my_pass = 'peanuts'.encode('utf8')
        iterations = 1
        key = PBKDF2(my_pass, salt, length, iterations)
        conn = sqlite3.connect(cookiesfile)
        cursor = conn.cursor()
        cursor.execute(
            'SELECT name, value, encrypted_value FROM cookies WHERE host_key == "' + url + '"')
        for name, value, encrypted_value in cursor.fetchall():
            decrypted_tuple = (name, chrome_decrypt(encrypted_value, key=key))
            cookies.append(decrypted_tuple)
    else:
        print('This tool is only supported by linux and Mac')

    conn.close()
    return cookies


if __name__ == '__main__':
    pass
else:
    salt = b'saltysalt'
    iv = b' ' * 16
    length = 16

#get_cookies('YOUR URL FROM THE COOKIES', 'YOUR PATH TO THE "/Default/Cookies" DATA')
Answered By: Tom

Toms answer has worked very well for me and was even the only way for me to work in Windows 7 to crawl through sites that require a login. However, with Windows 10 and the Chrome 80 cookie handling (SameSite Cookies) there seems to be a new encryption – the cookie delivered by the "get_cookies" method had all empty values (Python 3).

What worked for me now was browser_cookie3 (fork of browsercookie, was updated just some days ago to work with Chrome 80). I used this with request and selenium.

Install in an elevated prompt with

pip3 install browser-cookie3

Usage with request:

import browser_cookie3
cookies = browser_cookie3.chrome(domain_name='.google.com')
response = requests.get('http://www.google.com', verify=False, headers=headers, cookies=cookies, timeout=3)

Exchange google.com with the domain of the cookie you need. And be sure to include the timeout parameter or your script may freeze.
headers is just an object with all your headers, e.g.

headers = {
    "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36", 
    "Accept-Encoding":"gzip, deflate", 
    "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", 
    "DNT":"1",
    "Connection":"close", 
    "Upgrade-Insecure-Requests":"1"
}

or something like that.

Usage with selenium:

import browser_cookie3
driver = webdriver.Chrome('./chromedriver')
cookies = browser_cookie3.chrome(domain_name='.google.com')
for c in cookies:
    cookie = {'domain': c.domain, 'name': c.name, 'value': c.value, 'secure': c.secure and True or False}
    driver.add_cookie(cookie)
driver.get('http://www.google.com')

./chromedriver is where my chromedriver.exe lies.

Answered By: Trevor

By the grace of the Lord Jesus, here’s Tom’s answer adapted for my case: Ubuntu 20.04 / Brave 1.26.74 / Chromium 91, together with some print() debugging for the SQLite table.

import sqlite3, Crypto.Cipher.AES, Crypto.Protocol.KDF  # pip install pycrypto

def cookie_brave_decrypt(encrypted_value:bytes, key:bytes):
    plaintxt = Crypto.Cipher.AES.new(key, Crypto.Cipher.AES.MODE_CBC, IV=IV).decrypt(encrypted_value[3:])
    return plaintxt[:-plaintxt[-1]].decode('utf8')

def cookies_get(url:str, dbpath:str):
    key  = Crypto.Protocol.KDF.PBKDF2(PASSWORD.encode('utf8'), SALT, LENGTH, NITERS)
    conn = sqlite3.connect(dbpath)
    cur  = conn.cursor()

    print('n---------------------------------------------------------------#')
    cur.execute('PRAGMA table_info(cookies)')  #  "SELECT *  FROM sqlite_master  WHERE type ='table' AND name NOT LIKE 'sqlite_%'")
    for row in cur.fetchall():  print(row)
    print('n---------------------------------------------------------------#')
    cur.execute(f'SELECT *  FROM cookies')
    for row in cur.fetchall():  print(row)

    cur.execute(f'SELECT name,encrypted_value  FROM cookies  WHERE host_key = ?', [url])
    cookies = {name:cookie_brave_decrypt(encrypted_value,key) for name,encrypted_value in cur.fetchall()}
    print('n---------------------------------------------------------------#')
    for name,encrypted_value in cookies.items():  print(f'{name:32} {encrypted_value}')

    conn.close()
    return cookies

PASSWORD = 'peanuts'
SALT     = b'saltysalt'
NITERS   = 1
IV       = b' ' * 16
LENGTH   = 16
cookies  = cookies_get('.youtube.com', '/home/da/.config/BraveSoftware/Brave-Browser/Default/Cookies')
Answered By: étale-cohomology
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.