How do I send a POST request as a JSON?

335,995

Solution 1

If your server is expecting the POST request to be json, then you would need to add a header, and also serialize the data for your request...

Python 2.x

import json
import urllib2

data = {
        'ids': [12, 3, 4, 5, 6]
}

req = urllib2.Request('http://example.com/api/posts/create')
req.add_header('Content-Type', 'application/json')

response = urllib2.urlopen(req, json.dumps(data))

Python 3.x

https://stackoverflow.com/a/26876308/496445


If you don't specify the header, it will be the default application/x-www-form-urlencoded type.

Solution 2

I recommend using the incredible requests module.

http://docs.python-requests.org/en/v0.10.7/user/quickstart/#custom-headers

url = 'https://api.github.com/some/endpoint'
payload = {'some': 'data'}
headers = {'content-type': 'application/json'}

response = requests.post(url, data=json.dumps(payload), headers=headers)

Solution 3

For python 3.4.2, I found the following will work:

import urllib.request
import json

body = {'ids': [12, 14, 50]}
myurl = "http://www.testmycode.example"

req = urllib.request.Request(myurl)
req.add_header('Content-Type', 'application/json; charset=utf-8')
jsondata = json.dumps(body)
jsondataasbytes = jsondata.encode('utf-8')   # needs to be bytes
req.add_header('Content-Length', len(jsondataasbytes))
response = urllib.request.urlopen(req, jsondataasbytes)

Solution 4

This works perfect for Python 3.5, if the URL contains Query String / Parameter value,

Request URL = https://bah2.example/ws/rest/v1/concept/ Parameter value = 21f6bb43-98a1-419d-8f0c-8133669e40ca

import requests

url = 'https://bahbah2.example/ws/rest/v1/concept/21f6bb43-98a1-419d-8f0c-8133669e40ca'
data = {"name": "Value"}
r = requests.post(url, auth=('username', 'password'), json=data)
print(r.status_code)

Solution 5

Here is an example of how to use urllib.request object from Python standard library.

import urllib.request
import json
from pprint import pprint

url = "https://app.close.com/hackwithus/3d63efa04a08a9e0/"

values = {
    "first_name": "Vlad",
    "last_name": "Bezden",
    "urls": [
        "https://twitter.com/VladBezden",
        "https://github.com/vlad-bezden",
    ],
}


headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
}

data = json.dumps(values).encode("utf-8")
pprint(data)

try:
    req = urllib.request.Request(url, data, headers)
    with urllib.request.urlopen(req) as f:
        res = f.read()
    pprint(res.decode())
except Exception as e:
    pprint(e)
Share:
335,995
TIMEX
Author by

TIMEX

Updated on November 05, 2021

Comments

  • TIMEX
    TIMEX over 2 years
    data = {
            'ids': [12, 3, 4, 5, 6 , ...]
        }
        urllib2.urlopen("http://abc.com/api/posts/create",urllib.urlencode(data))
    

    I want to send a POST request, but one of the fields should be a list of numbers. How can I do that ? (JSON?)

  • zakdances
    zakdances over 10 years
    This gives me TypeError: post() takes from 1 to 2 positional arguments but 3 were given
  • psukys
    psukys over 7 years
    in your code snipper, headers variable stays unused
  • Omar Jandali
    Omar Jandali over 6 years
    I have a question. is it possible to add multiple items in the header... like content type & client-id... @jdi
  • jdi
    jdi over 6 years
    @OmarJandali, just call add_header() again, for each header you want to add.
  • Omar Jandali
    Omar Jandali over 6 years
    i have the following coded but it is not printing anything. it was supposed to print the url and headers but nothing was printed... req = urllib.Request('http://uat-api.synapsefi.com') req.add_header('X-SP-GATEWAY', 'client_id_asdfeavea561va9685e1gre5ara|client_secret_4651av5‌​sa1edgvawegv1a6we1v5‌​a6s51gv') req.add_header('X-SP-USER-IP', '127.0.0.1') req.add_header('X-SP-USER', '| ge85a41v8e16v1a618gea164g65') req.add_header('Content-Type', 'application/json') print(req)...
  • Omar Jandali
    Omar Jandali over 6 years
    urllib2 was not recognized so i just used urllib. i am also getting an error with the request. The view tab.views.profileSetup didn't return an HttpResponse object. It returned None instead. @jdi
  • jdi
    jdi over 6 years
    @OmarJandali, please keep in mind that this answer was originally given in 2012, under python 2.x. You are using Python3 so the imports will be different. It would now be import urllib.request and urllib.request.Request(). Furthermore, printing the req object does nothing interesting. You can clearly see the headers have been added by printing req.headers. Beyond that, I am not sur why it isn't working in your application.
  • Omar Jandali
    Omar Jandali over 6 years
    So i have two lines that i made changes to response = urllib.request.Request(req, json.dumps(data)) and req = urllib.request.Request('http://uat-api.synapsefi.com'). i am getting a message saying unknown url type: 'urllib.request.Request object at 0x00000250B05474A8' from the second line that i made changes to... what is the way fro me to change the url type @jdi
  • jdi
    jdi over 6 years
    @OmarJandali, you aren't calling urlopen() like the original example. That is why you are getting an error. See: pastebin.com/1gUdGYcP
  • Omar Jandali
    Omar Jandali over 6 years
  • Omar Jandali
    Omar Jandali over 6 years
    Than you so much, it is working and sending a response. it is sending a response in the wrong format POST data should be bytes, an iterable of bytes, or a file object. It cannot be of type str.
  • Shalin LK
    Shalin LK over 6 years
    Python3.6.2 this worked. Only adding header with req.add_header(...) worked for me.
  • Kuzeko
    Kuzeko about 6 years
    The python3 version is the one here: stackoverflow.com/a/26876308/5973334 – better merge it with the accepted answer
  • jdi
    jdi about 6 years
    @Kuzeko, thanks. I have added that reference to my answer
  • Jethro
    Jethro about 4 years
    Note that this will result in POSTed json with single quotes, which is technically invalid.
  • jdhao
    jdhao about 4 years
    @Jethro Have you observed errors when using single quotes? It is valid to use single quotes in Python. Personally, I haven't met any issues regarding this.
  • Jethro
    Jethro about 4 years
    Aah apologies I was mistaken, I thought my server was receiving single-quoted JSON but It turned out to be a separate issue and some misleading debugging. Cheers, this is much tidier than having to specify the header manually!
  • rgov
    rgov over 2 years
    This is an incorrect answer. The data=data parameter sends a form-encoded request, which is not JSON. Use json=data instead.
  • rgov
    rgov over 2 years
    Note: This answer is very old and urllib2 has been removed in Python 3. Look for other examples using urllib or requests.
  • rgov
    rgov over 2 years
    It is much more succinct to just use json=payload (which may have been introduced since this answer was written long ago) without specifying the header or calling json.dumps(). See other answers on this page.
  • rgov
    rgov over 2 years
    You do not need to specify the Content-Length header, it will be calculated by urllib automatically.
  • rgov
    rgov over 2 years
    This answer is insecure. Do not pass verify=False, which disables certificate validation and opens your code up to man-the-middle attacks.
  • rgov
    rgov over 2 years
    I removed verify=False from the code sample to resolve the above comment.
  • Apurva Singh
    Apurva Singh almost 2 years
    works great using standard library urllib. Don't forget the data in Request(url, data, headers), otherwise it would look like a GET to the server.