Getting 403 Forbidden error when requesting JSON output with apikey - python

I am trying to request information from a server with Python. The API key is correct however I still get the 403 error. It works with curl, but not with Python.
Here is the curl code that outputs JSON:
curl -H "apiKey: xxx" https://kretaglobalmobileapi.ekreta.hu/api/v1/Institute/3928
And here is my code that outputs Forbidden error:
from urllib.request import Request, urlopen
import json
ker = Request('https://kretaglobalmobileapi.ekreta.hu/api/v1/Institute/3928')
ker.add_header('apiKey', 'xxxx')
content = json.loads(urlopen(ker))
print(content)
What is the problem?

urlopen usually returns a HTTPResponse object. So in order to read the contents use the read() function. Other wise your code looks fine.
req = Request('https://kretaglobalmobileapi.ekreta.hu/api/v1/Institute/3928')
req.add_header('apikey', 'xxx')
content = urlopen(req).read()
print(content).
You can also use another library for instance requests if the above method dosent work,
r = requests.get('<MY_URI>', headers={'apikey': 'xxx'})

Related

401 response with Python requests

I'am using library "requests" for get image from url ('http://any_login:any_password#10.10.9.2/ISAPI/Streaming/channels/101/picture?snapShotImageType=JPEG'), but response error with code 401. Thats url from my rtsp camera.
I try using 'HTTPBasicAuth', 'HTTPDigestAuth' and 'HTTPProxyAuth'. But it's not working.
import requests
from requests.auth import HTTPBasicAuth
url = "http://any_login:any_password#10.10.9.2/ISAPI/Streaming/channels/101/picture?snapShotImageType=JPEG"
response = requests.get(url, auth=requests.auth.HTTPBasicAuth("any_login", "any_password"))
if response.status_code == 200:
with open("sample.jpg", 'wb') as f:
f.write(response.content)
I expected the output of image file from rtsp flow, but I got error code 401.
Given your username I suspect your password may contain non-ASCII characters. I had a similar issue with a password containing diacritics.
This worked :
curl -u user:pwd --basic https://example.org
This (and variations) throwed 401 Unauthorized :
import requests
requests.get("https://example.org", auth=requests.auth.HTTPBasicAuth("user","pwd"))
Changing the password to ASCII only characters solved the issue.

Using requests in Python to process GET request

I posted another question but made a bit of a mess of it in the comments section. Basically, I am trying to use the requests library in Python in order to accomplish what I normally would by using CURL in order to process a GET request to an API. From what I have learned from a very helpful person here, I can process the request, as well as the authorisation header by doing the following:
Original CURL Command that I would normally use:
curl -X GET -H 'Authorization: exapi:111:58d351234e1a:LA2' 'http://api.example.com/v1.14/user?id=1234'
This is the Python code I am using for my script:
import requests
import json
url = "http://api.example.com/v1.14/user?id=1234"
headers = {"Authorization": "exapi:111:58d351234e1a:LA2"}
response = requests.get(url, headers=headers)
print response.json
However, when I run my code, I receive bound method response.json of <response [200]> instead of data that I was expecting from the GET. Can someone help me figure out what I am doing wrong here? I am guessing that I am doing something wrong with my header but I am not sure.
As #juanpa.arrivilaga has already mentioned and as the printed message clearly says, you need to call the bound json method. The source of confusion is likely from content, which is an attribute.
response.json() # method
response.content # attribute
How about using json module explicitly:
data = json.loads(response.text)
print data

API response with a proxy is working with the curl, but nothing is returned with python

I am trying to access data using API which is behind the proxy server. If I use curl command like below it works:
curl --proxy http://MY_PROXY_SERVER:PORT --header "Accept: application/csv" http://WEB_SERVER_ADDRESS/data/CHANNEL?start=1470011400
I get the data which is expected.
When I am trying to access the same URL with python either by requests or urllib2 I am not able to get the data back. This is the code:
from __future__ import print_function
import requests
s = requests.Session()
s.proxies = {"http": "http://MY_PROXY_SERVER:PORT"}
headers = {'Accept': 'application/csv'}
url = "http://WEB_SERVER_ADDRESS/data/CHANNEL?start=1470011400"
r = s.get(url, headers=headers)
print(r.text)
I don't get any error and request is able to go through the python successfully. The output is empty list. I also tried with other media type supported by API like 'json', issue still persists.

how to encode POST data using python's urllib

I'm trying to connect to my Django server using a client side python script. Right now I'm just trying to connect to a view and retrieve the HttpResponse. The following works fine
import urllib2
import urllib
url = "http://localhost:8000/minion/serve"
request = urllib2.Request(url)
response = urllib2.urlopen(request)
html = response.read()
print html
However if I change it to
import urllib2
import urllib
url = "http://localhost:8000/minion/serve"
values = {'name': 'Bob'}
data = urllib.urlencode(values)
request = urllib2.Request(url, data)
response = urllib2.urlopen(request)
html = response.read()
print html
I get urllib2.HTTPError: HTTP Error 500: INTERNAL SERVER ERROR. Am I doing something wrong here? Here are the tutorials I was trying to follow, http://techmalt.com/?p=212 http://docs.python.org/2/howto/urllib2.html.
EDIT: tried to make the following change as per That1Guy's suggestion (other lines left the same)
request = urllib2.Request(url, data)
response = urllib2.urlopen(request, data)
This returned the same error message as before.
EDIT: It seems to work if I change the page I'm viewing so the error isn't in the client side script. So in light of that revelation, here's the server side view that's being accessed:
def serve(request):
return HttpResponse("You've been served!")
As you can see, it's very straight forward.
EDIT: Tested to see if Internal Error might be caused by missing csrf token, but csrf_exempt decorator failed to resolve error.
Finally figured it out with this. How to POST dictionary from python script to django url?
Turns out my url was missing a trailing slash. It's the little things that always get you I guess.

Python Requests Invalid URL Label error

I'm trying to access Shopify's API which uses a URL format of -
https://apikey:password#hostname/admin/resource.xml
e.g.http://7ea7a2ff231f9f7:95c5e8091839609c864#iliketurtles.myshopify.com/admin/orders.xml
doing $curl api_url downloads the correct XML however when I do
import requests
api_url = 'http://7ea7a2ff231f9f7d:95c5e8091839609c864#iliketurtles.myshopify.com/admin/orders.xml'
r = requests.get(api_url) # Invalid url label error
Any idea why I'm getting this? Curl / opening the link directly in the browser is working fine. Is it because the length of the URL is too long?
Thanks!
The error ('URL has an invalid label.') is probably a bug in requests library: it applies idna encoding (for internationalized domain names) on hostname with userinfo attached, source:
netloc = netloc.encode('idna').decode('utf-8')
that might raise 'label empty or too long' error for the long username:password. You can try to report it on the requests' issue tracker.
a:b#example.com form is deprecated otherwise
requests.get('https://a:b#example.com') should be equivalent to requests.get('https://example.com', auth=('a', 'b')) if all characters in username:password are from [-A-Za-z0-9._~!$&'()*+,;=] set.
curl and requests also differ then there are percent-encoded characters in userinfo e.g., https://a:%C3%80#example.com leads to curl generating the following http header:
Authorization: Basic YTrDgA==
but requests produces:
Authorization: Basic YTolQzMlODA=
i.e.:
>>> import base64
>>> base64.b64decode('YTrDgA==')
'a:\xc3\x80'
>>> print _
a:À
>>> base64.b64decode('YTolQzMlODA=')
'a:%C3%80'
It's not the length of the URL. If I do:
import requests
test_url = 'http://www.google.com/?somereallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallylongurl=true'
r = requests.get(test_url)
returns <Response [200]>
Have you tried making the request with the requests Authentication parameters detailed here
>>> requests.get('http://iliketurtles.myshopify.com/admin/orders.xml', auth=('ea7a2ff231f9f7', '95c5e8091839609c864'))
<Response [403]>

Categories

Resources