325

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?

jps
  • 20,041
  • 15
  • 75
  • 79
user1113569
  • 3,441
  • 2
  • 14
  • 10
  • 1
    Post request is just post request, regardless what's on server side. – Ondra Žižka Jul 04 '12 at 04:35
  • 8
    This sends a POST request. Then the server responds with 302 (redirect) headers to your POST. What is actually wrong? – ddinchev Jul 04 '12 at 04:41
  • 1
    This script doesn't look python3.2 compat – jdi Jul 04 '12 at 05:10
  • python3 equivalent of this example might be: http://pastebin.com/Rx4yfknM – jdi Jul 04 '12 at 05:39
  • 1
    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. – RanRag Jul 04 '12 at 06:48

7 Answers7

484

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...
>>> 
Brōtsyorfuzthrāx
  • 4,387
  • 4
  • 34
  • 56
  • 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. – Efe Büyük May 05 '17 at 11:31
  • for the record: a working code recently for me, data={'@number': '12524', '@type': 'issue', '@action': 'show'} – marr Jan 05 '18 at 03:46
  • 2
    How to get json result? – Yohanim Apr 26 '18 at 09:03
  • 28
    If you need to send a JSON object you should do: `json={'number': 12524...` instead of `data=...` – Seraf Aug 29 '18 at 17:34
  • 7
    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? – Jan Pisl Oct 29 '19 at 17:02
  • 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 Python – Sam Firke Feb 18 '22 at 17:09
185

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())
json = urlopen(request).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"
}
stil
  • 5,306
  • 3
  • 38
  • 44
38

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))
waterproof
  • 4,943
  • 5
  • 30
  • 28
d1jhoni1b
  • 7,497
  • 1
  • 51
  • 37
22

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)
Pikamander2
  • 7,332
  • 3
  • 48
  • 69
Pranzell
  • 2,275
  • 16
  • 21
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/

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.

Phil
  • 2,238
  • 2
  • 23
  • 34
2

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)

dejanualex
  • 3,872
  • 6
  • 22
  • 37
Nkgupta
  • 144
  • 1
  • 6