Search code examples
wordpresspython-requestswordpress-rest-api

Why does Python Requests cause an HTTP 400 error but POSTing in Postman and Curl does not?


I can't see what I am doing wrong here. I can post successfully to HTTPBIN from Python, post to my website using Curl and I can post to my Wordpress website using Postman. HTTPBIN looks like this:

200
{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "password": "1234 abcd 5678 edfg 9012 hijk", 
    "username": "johnnyjohnboy"
  }, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Content-Length": "61", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.28.2", 
    "X-Amzn-Trace-Id": "Root=1-234234234-234234234234234234"
  }, 
  "json": null, 
  "origin": "12.12.12.121", 
  "url": "https://httpbin.org/post"
}

Using this curl command I get success too:

curl -H "Content-type: multipart/form-data" \
     -F username=johnnyjohnboy \
     -F password="1234 abcd 5678 edfg 9012 hijk" \
     -X POST \
     https://www.mywebsite.co.uk/wp-json/jwt-auth/v1/token

What I can't do is POST to my website from Python,

This is what I am using:

resp = requests.post('https://www.mywebsite.co.uk/wp-json/jwt-auth/v1/token', data={"username": "johnnyjohnboy", "password": "1234 abcd 5678 edfg 9012 hijk"})
print(resp.status_code)
print(resp.text)


# 400
# 400 - Bad Request | Your browser sent a request this server could not understand.

I can see in Postman it's a POST request to the same URL and application/x-www-form-urlencoded and that it looks like username=johnnyjohnboy&password=1234+abcd+5678+edfg+9012+hijk.

The code even worked up until a couple of days ago and since then, nothing.. it's a Wordpress site so could have been auto updated somehow but I can't see how that would make any difference when Postman still works.

I literally cannot see the wood from the trees..


Solution

  • This was resolved by adding arbitrary headers to the request like this, it didn't matter what they were so I just used a random one. Wordpress 6.2 just suddenly wanted them to access the API.

    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0'
    }
    
    resp = requests.post('https://www.mywebsite.co.uk/wp-json/jwt-auth/v1/token', headers=headers, data={"username": "johnnyjohnboy", "password": "1234 abcd 5678 edfg 9012 hijk"})
    print(resp.status_code)
    print(resp.text)