20

When I use requests to access an URL cookies are automatically sent back to the server (in the following example the requested URL set some cookie values and then redirect to another URL that display the stored cookie)

>>> import requests
>>> response = requests.get("http://httpbin.org/cookies/set?k1=v1&k2=v2")
>>> response.content
'{\n  "cookies": {\n    "k2": "v2",\n    "k1": "v1"\n  }\n}'

Is it possible to temporary disable cookie handling in the same way you set Chrome or Firefox to not accept cookies?

For example if I access the aforementioned URL with Chrome with cookie handling disabled I get what I expected:

{
  "cookies": {}
}
raben
  • 3,060
  • 5
  • 32
  • 34
  • 1
    [Requests - Cookies](http://docs.python-requests.org/en/latest/user/quickstart/#cookies) from the documentation, they don't mention anything about disabling cookies. But, you can take a look at https://github.com/kennethreitz/requests/blob/master/requests/cookies.py and https://github.com/kennethreitz/requests/blob/master/requests/sessions.py on how it handles cookiejars. – bnlucas Jun 11 '13 at 06:54

5 Answers5

32

You can do this by defining a cookie policy to reject all cookies:

from http import cookiejar  # Python 2: import cookielib as cookiejar
class BlockAll(cookiejar.CookiePolicy):
    return_ok = set_ok = domain_return_ok = path_return_ok = lambda self, *args, **kwargs: False
    netscape = True
    rfc2965 = hide_cookie2 = False

(Note that http.cookiejar's API requires you to define a bunch of attributes and methods, as shown.)

Then, set the cookie policy on your Requests session:

import requests
s = requests.Session()
s.cookies.set_policy(BlockAll())

It will now not store or send cookies:

s.get("https://httpbin.org/cookies/set?foo=bar")
assert not s.cookies

As an aside, if you look at the code, the convenience methods in the requests package (as opposed to those on a requests.Session object) construct a new Session each time. Therefore, cookies aren't persisted between separate calls to requests.get. However, if the first page sets cookies and then issues an HTTP redirect, the target page will see the cookies. (This is what happens with the HTTPBin /cookies/set call, which redirects to /cookies.)

So depending on what behavior you want for redirects, you might not need to do anything special. Compare:

>>> print(requests.get("https://httpbin.org/cookies/set?foo=bar").json())
{'cookies': {'foo': 'bar'}}
>>> print(requests.get("https://httpbin.org/cookies").json())
{'cookies': {}}

>>> s = requests.Session()
>>> print(s.get("https://httpbin.org/cookies/set?foo=bar").json())
{'cookies': {'foo': 'bar'}}
>>> print(s.get("https://httpbin.org/cookies").json())
{'cookies': {'foo': 'bar'}}

>>> s = requests.Session()
>>> s.cookies.set_policy(BlockAll())
>>> print(s.get("https://httpbin.org/cookies/set?foo=bar").json())
{'cookies': {}}
>>> print(requests.get("https://httpbin.org/cookies").json())
{'cookies': {}}
Mechanical snail
  • 29,755
  • 14
  • 88
  • 113
  • Thanks for the very comprehensive, clear and detailed response. In particular for the explanation regarding httpbin redirect. – raben Feb 12 '14 at 12:37
1

A simpler alternative to creating a new class is to use http.cookiejar.DefaultCookiePolicy with an empty list of allowed domains:

from requests import Session
from http.cookiejar import DefaultCookiePolicy

s = Session()
s.cookies.set_policy(DefaultCookiePolicy(allowed_domains=[]))

From the documentation:

allowed_domains: if not None, this is a sequence of the only domains for which we accept and return cookies

bfontaine
  • 18,169
  • 13
  • 73
  • 107
0

You're getting back "k2": "v2", "k1": "v1" because they're sent in GET params. If you follow up with a second request you'll see you send no cookies. Unless you use requests.Session cookies are not automatically handled in the client and you have to explicitly pass a dict or CookieJar with each request.

In [17]: r = requests.get("http://httpbin.org/cookies/set?k1=v1&k2=v2")

In [18]: r.content
Out[18]: '{\n  "cookies": {\n    "k2": "v2",\n    "k1": "v1"\n  }\n}'

In [20]: r.cookies.get_dict()
Out[20]: {}

In [21]: r = requests.get("http://httpbin.org/cookies")

In [22]: r.content
Out[22]: '{\n  "cookies": {}\n}'
radu.ciorba
  • 1,024
  • 1
  • 8
  • 14
  • 2
    When you make a request to that URL the first response from the server set a cookie in the client. Than you are redirected to a new URL that displays the content of the cookie that has been set by the first response. This is the way httpbin.org works specifically to test cookie persistence. Try to get the same URL with your browser with cookies disabled and you will get an empty answer. – raben Jun 11 '13 at 09:22
0
>>> import mock
>>> import requests
>>> with mock.patch.object(requests.cookies.RequestsCookieJar, 'update', lambda *args, **kwargs: 0):
...     r = requests.get("http://httpbin.org/cookies/set?k1=v1&k2=v2")#, cookies=cj)
...     r.content
... 
'{\n  "cookies": {}\n}'
>>> r = requests.get("http://httpbin.org/cookies/set?k1=v1&k2=v2")
>>> r.content
'{\n  "cookies": {\n    "k2": "v2",\n    "k1": "v1"\n  }\n}'
falsetru
  • 357,413
  • 63
  • 732
  • 636
  • I see that it works, but I do not fully understand what is happening. Do you mind to explain a bit? – raben Jun 11 '13 at 09:25
  • 1
    This code patch requests.cookies.RequestsCookieJar.update method to not update cookie. Outside the with block, the patch is undone. – falsetru Jun 11 '13 at 09:27
-1
class BlockAll(CookiePolicy):
    def set_ok(self, cookie, request):
        return False
session.cookies.policy = BlockAll()
miracle2k
  • 29,597
  • 21
  • 65
  • 64