How to send POST request?
Asked Answered
P

7

335

I found this script online:

import httplib, urllib
params = urllib.urlencode({'number': 12524, 'type': 'issue', 'action': 'show'})
headers = {"Content-type": "application/x-www-form-urlencoded",
            "Accept": "text/plain"}
conn = httplib.HTTPConnection("bugs.python.org")
conn.request("POST", "", params, headers)
response = conn.getresponse()
print response.status, response.reason
302 Found
data = response.read()
data
'Redirecting to <a href="http://bugs.python.org/issue12524">http://bugs.python.org/issue12524</a>'
conn.close()

But I don't understand how to use it with PHP or what everything inside the params variable is or how to use it. Can I please have a little help with trying to get this to work?

Polymerize answered 4/7, 2012 at 4:30 Comment(6)
Post request is just post request, regardless what's on server side.Gobbet
This sends a POST request. Then the server responds with 302 (redirect) headers to your POST. What is actually wrong?Helton
This script doesn't look python3.2 compatPreordain
python3 equivalent of this example might be: pastebin.com/Rx4yfknMPreordain
What I will suggest is install firefox's live http header addon and than open your url in firefox and see the request/response of url in live http header addon than you will understand what params and headers do in your code.Tindal
I like the combination of statements "I don't understand how to use it with PHP" and "I am using Python 3.2" in the original text =DClubbable
B
492

If you really want to handle with HTTP using Python, I highly recommend Requests: HTTP for Humans. The POST quickstart adapted to your question is:

>>> import requests
>>> r = requests.post("http://bugs.python.org", data={'number': '12524', 'type': 'issue', 'action': 'show'})
>>> print(r.status_code, r.reason)
200 OK
>>> print(r.text[:300] + '...')

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>
Issue 12524: change httplib docs POST example - Python tracker

</title>
<link rel="shortcut i...
>>> 
Bother answered 4/7, 2012 at 8:8 Comment(7)
I cannot get the same result as you did above. I wrote another issue number on the page and then run the script but I could not see the Issue number on the result.Bisset
for the record: a working code recently for me, data={'@number': '12524', '@type': 'issue', '@action': 'show'}Pedantry
How to get json result?Venetis
If you need to send a JSON object you should do: json={'number': 12524... instead of data=...Mota
why does the answer say "If you really want to handle with HTTP using Python"? is it a bad idea to handle HTTP requests? if so, why? can anyone explain please?Lipinski
In some dialects of English, that use of "really" could mean "properly" or "truly" - i.e., this is the full, serious, proper way to handle HTTP with PythonSolicitude
I think they meant to clarify the context since OP asked something about PHPClubbable
L
189

This is a solution without any external pip dependencies, but works only in Python 3+ (Python 2 won't work):

from urllib.parse import urlencode
from urllib.request import Request, urlopen

url = 'https://httpbin.org/post' # Set destination URL here
post_fields = {'foo': 'bar'}     # Set POST fields here

request = Request(url, urlencode(post_fields).encode())
with urlopen(request) as response:
    json = response.read().decode()
print(json)

Sample output:

{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "foo": "bar"
  }, 
  "headers": {
    "Accept-Encoding": "identity", 
    "Content-Length": "7", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "httpbin.org", 
    "User-Agent": "Python-urllib/3.3"
  }, 
  "json": null, 
  "origin": "127.0.0.1", 
  "url": "https://httpbin.org/post"
}
Linguini answered 17/4, 2016 at 15:30 Comment(0)
J
39

You can't achieve POST requests using urllib (only for GET), instead try using requests module, e.g.:

Example 1.0:

import requests

base_url="www.server.com"
final_url="/{0}/friendly/{1}/url".format(base_url,any_value_here)

payload = {'number': 2, 'value': 1}
response = requests.post(final_url, data=payload)

print(response.text) #TEXT/HTML
print(response.status_code, response.reason) #HTTP

Example 1.2:

>>> import requests

>>> payload = {'key1': 'value1', 'key2': 'value2'}

>>> r = requests.post("http://httpbin.org/post", data=payload)
>>> print(r.text)
{
  ...
  "form": {
    "key2": "value2",
    "key1": "value1"
  },
  ...
}

Example 1.3:

>>> import json

>>> url = 'https://api.github.com/some/endpoint'
>>> payload = {'some': 'data'}

>>> r = requests.post(url, data=json.dumps(payload))
Jaf answered 10/4, 2016 at 7:49 Comment(2)
Thanks. data=json.dumps(payload) is the key for my usecaseWainscoting
replace "data" with "json" would also do the trickAbate
D
23

Use requests library to GET, POST, PUT or DELETE by hitting a REST API endpoint. Pass the rest api endpoint url in url, payload(dict) in data and header/metadata in headers

import requests, json

url = "bugs.python.org"

payload = {"number": 12524, 
           "type": "issue", 
           "action": "show"}

header = {"Content-type": "application/x-www-form-urlencoded",
          "Accept": "text/plain"} 

response_decoded_json = requests.post(url, data=payload, headers=header)
response_json = response_decoded_json.json()
 
print(response_json)
Desdamona answered 5/12, 2018 at 8:38 Comment(3)
This code has issues with indentation and the header param name.Readjustment
headers parameter is wrong and also we have not any json here. We should use json.dumps(pauload)Himeji
Thanks @Readjustment and ArashHatami for the syntax error. Corrected now.Desdamona
C
6

Your data dictionary conteines names of form input fields, you just keep on right their values to find results. form view Header configures browser to retrieve type of data you declare. With requests library it's easy to send POST:

import requests

url = "https://bugs.python.org"
data = {'@number': 12524, '@type': 'issue', '@action': 'show'}
headers = {"Content-type": "application/x-www-form-urlencoded", "Accept":"text/plain"}
response = requests.post(url, data=data, headers=headers)

print(response.text)

More about Request object: https://requests.readthedocs.io/en/master/api/

Collaboration answered 20/1, 2020 at 14:28 Comment(0)
E
3

If you don't want to use a module you have to install like requests, and your use case is very basic, then you can use urllib2

urllib2.urlopen(url, body)

See the documentation for urllib2 here: https://docs.python.org/2/library/urllib2.html.

Endarch answered 17/1, 2019 at 20:17 Comment(0)
A
3

You can use the request library to make a post request. If you have a JSON string in the payload you can use json.dumps(payload) which is the expected form of payload.


    import requests, json
    url = "http://bugs.python.org/test"
    payload={
        "data1":1234,'data2':'test'
    }
    headers = {
        'Content-Type': 'application/json'
    }
    response = requests.post(url, headers=headers, data=json.dumps(payload))
    print(response.text , response.status_code)

Altheaalthee answered 10/9, 2021 at 2:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.