5

My intention is to log into a site and then access a protected image from a python script. I have both legal and working access from a browser.

This is what I have now.

import requests

s = requests.Session()

s.get('*domain*')

r_login  =s.post('*domain*/user.php', headers={'cmd': 'login', 'loginname': '***', 'password': '***' })

print (s.cookies)
print (r_login.status_code)

r_img = s.get('*domain*/*protectedimage*.jpg')
print (r_img.status_code)
print (r.cookies)

print (s.cookies['PHPSESSID'])

Output:

<<class 'requests.cookies.RequestsCookieJar'>[<Cookie PHPSESSID=664b0842085b847a04d415a22e013ad8 for *domain*/>]>
200
403
<<class 'requests.cookies.RequestsCookieJar'>[]>
664b0842085b847a04d415a22e013ad8

I am sure I can successfully log in, because I have once downloaded the html file after doing so, and it was in a form of being logged in. But my problem is that it seems to me that my PHPSESSID cookie does not pass so I get a 403 error back. But I clearly have it in my session. I have also tried adding the cookie manually to my "r_img" line, and it made no difference, I still get an empty CookieJar and a 403 error back. Would this be not possible with only the requests modul? Did I overlook something? Excuse me for being not quite familiar with HTTP requests.

I'm using Python 3.4 just for sake of clarity.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Tigris
  • 119
  • 1
  • 8
  • Most probably you should not be setting cookies, but POST data. Cookies would be set by the server your are posting to. See my answer. – data Jun 17 '14 at 09:42

2 Answers2

5

You are passing in your form data as HTTP headers. A POST login form should send form elements as the data parameter instead:

r_login = s.post('*domain*/user.php', 
                 data={'cmd': 'login', 'loginname': '***', 'password': '***' })

Do inspect the returned body, not just the status code. Your POST request was accepted by the server (200 OK) but since no login information was posted, the body will most likely tell you something like "login incorrect, please try again".

The server most likely cleared the cookie again seeing as it was not a valid login session when you requested the image. The 403 response probably contains a Set-Cookie header for PHPSESSID with a date in the past to clear it.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • Works wonderful! Thank you very much. I did not know that about post methods. All I had to do is just change the word "headers" to "data". :) Now I am able to download my image. _file = open('myimg.jpg', 'wb') file.write(r_img.content) file.close()_ – Tigris Jun 17 '14 at 09:55
  • 1
    @Tigris: to download (larger) images, consider streaming the download so as not to store the whole download in memory first. See [How to download image using requests](http://stackoverflow.com/q/13137817) – Martijn Pieters Jun 17 '14 at 15:19
  • Thanks again. Fortunately I had to only get some small images. :) – Tigris Jun 17 '14 at 16:45
3

Try doing it like this:

As per python-requests docs:

payload = {'cmd': 'login', 'loginname': '***', 'password': '***'}
url = '*domain*/user.php'
s.post(url, data=payload)
data
  • 2,563
  • 1
  • 21
  • 25
  • Thanks, sticking more strictly to the documentation would have been one solution. – Tigris Jun 17 '14 at 09:56
  • @Tigris could you please elaborate why did you accept Martjin's answer and not mine? We have the exact same code and I answered 5 minutes before him. – data Jun 17 '14 at 10:26
  • 4
    Yes, I'm sorry I did not consider the time at deciding which to choose, I both marked your answers helpful, but Martjin also provided me with the detailed explanation. I really needed to know that a POST method must be sent in a "data" parameter, that bit solved my problem. – Tigris Jun 17 '14 at 11:04