7

I am using python requests module, I send my params like this before:

requests.post(url=url, params=params)

but today, I find that I send my data like this, it fails, I change to this:

requests.post(url=url, data=params)

then it is ok, what is the difference between data and params?

I observed that the request got a header X-Requested-With:XMLHttpRequest, is it because of this?

pnuts
  • 54,806
  • 9
  • 74
  • 122
roger
  • 6,477
  • 13
  • 55
  • 102
  • Are you sure you weren't getting rather than posting? – Peter Wood Nov 03 '15 at 10:44
  • what was the error you got when sending it in params? – Ross Drew Nov 03 '15 at 11:01
  • TO EVERYONE: take into account that the accepted answer had several errors for years. I answered it properly 2 years ago, and the guy of the accepted answer just edited his own errors with my information, today (you can check it reviewing the history of editions). That's a very bad behaviour, taking someone else's credit. If the owner of the question doesn't do anything (marking mine as the correct one), at least you all don't upvote the accepted answer, that's the type of actions we have to remove from StackOverflow. – thelawnmowerman Jun 10 '20 at 11:21

3 Answers3

9

According to the requests documentation:

  • A requests.post(url, data=data) will make an HTTP POST request, and
  • A requests.get(url, params=params) will make an HTTP GET request

To understand the difference between the two, see this answer.

Here's how params can be used in a GET:

payload = {'key1': 'value1', 'key2': 'value2'}
r = requests.get('http://httpbin.org/get', params=payload)
print(r.text)

Which outputs

{
  "args": {
    "key1": "value1", 
    "key2": "value2"
  }, 
  [...]
  "url": "http://httpbin.org/get?key1=value1&key2=value2"
}

Notice that the payload ended up in the query string of the URL. Since they ended up there, they are viewable by anyone who has access to the URL, which is why you shouldn't use query strings for sensitive data like passwords.

Here's how data can be used in a POST:

payload = 'foobar'
r = requests.post('http://httpbin.org/post', data=payload)
print(r.text)

Which outputs

{
  "args": {}, 
  "data": "foobar", 
  [...]
  "url": "http://httpbin.org/post"
}

Notice how the POST data does not show up in the query strings, as they are transmitted through the body of the request instead.


Critique of this answer has pointed out that there are more options. I never denied such a thing in my original answer, but let's take a closer look.

The documentation examples always show:

  • The params keyword used for GET, and
  • The data keyword used for POST

But that doesn't mean they are mutually exclusive.

In theory you could mix the two together in a POST:

data = 'foobar'
params = {'key1': 'value1', 'key2': 'value2'}
r = requests.post('http://httpbin.org/post', params=params, data=data)
print(r.text)

Which outputs

{
  "args": {
    "key1": "value1", 
    "key2": "value2"
  }, 
  "data": "foobar", 
  [...]
  "url": "http://httpbin.org/post?key1=value1&key2=value2"
}

But you cannot mix data into a GET:

data = 'foobar'
params = {'key1': 'value1', 'key2': 'value2'}
r = requests.get('http://httpbin.org/get', params=params, data=data)
print(r.text)

Outputs:

{
  "args": {
    "key1": "value1", 
    "key2": "value2"
  }, 
  [...]
  "url": "http://httpbin.org/get?key1=value1&key2=value2"
}

Notice how the data field is gone.

ZN13
  • 646
  • 7
  • 19
  • post will not send data in URL. get method does. – Sekar Ramu Nov 15 '18 at 13:25
  • @SekarRamu It seems that the code example I wrote was right, but I mistyped the text above so instead of `requests.get` I wrote `requests.post`. This should now be fixed. – ZN13 Dec 04 '18 at 16:28
5

First of all, there are two different methods:

  • requests.post() makes a POST request (placing all the parameters in the body)
  • requests.get() makes a GET request (placing all the parameters in the URL)

Then, according to the docs, you can choose between two parameters to send all the key/value data:

  • params=, without string modifications.
  • data=, applying a form-encoding string modification to the parameters.

So, you have 4 choices to send your request:

  • requests.post(url, params=)
  • requests.post(url, data=)
  • requests.get(url, params=)
  • requests.get(url, data=)

I don't think the currently accepted answer is correct. He is actually talking about requests.post() but using requests.get() in his own example.

thelawnmowerman
  • 1,516
  • 1
  • 14
  • 30
  • Wrong. You cannot use the data keyword in a GET request. It just silently removes it. – ZN13 Jun 10 '20 at 07:29
1

Params are sent in (appended to) the URI (http://www.answer.com/here?param1=1&param2=2) while data is sent in the request body. Usually sensitive data or that sent in large volumes is posted in the body because it's easier to secure and doesn't lead to huge URIs.

Community
  • 1
  • 1
Ross Drew
  • 7,575
  • 2
  • 36
  • 51