POSTing JSON Data With PHP cURL

I got this question the other day: how to send a POST request from PHP with correctly-formatted JSON data? I referred to the slides from my web services tutorial for the answer, and I thought I'd also put it here, with a bit of explanation. After all, publishing your slides is all very well, but if you didn't see the actual tutorial, I often think they aren't too useful.

We can't send post fields, because we want to send JSON, not pretend to be a form (the merits of an API which accepts POST requests with data in form-format is an interesting debate). Instead, we create the correct JSON data, set that as the body of the POST request, and also set the headers correctly so that the server that receives this request will understand what we sent:

$data = array("name" => "Hagrid", "age" => "36");                                                                    
$data_string = json_encode($data);                                                                                   
 
$ch = curl_init('http://api.local/rest/users');                                                                      
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");                                                                     
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);                                                                  
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);                                                                      
curl_setopt($ch, CURLOPT_HTTPHEADER, array(                                                                          
    'Content-Type: application/json',                                                                                
    'Content-Length: ' . strlen($data_string))                                                                       
);                                                                                                                   
 
$result = curl_exec($ch);

All these settings are pretty well explained on the curl_setopt() page, but basically the idea is to set the request to be a POST request, set the json-encoded data to be the body, and then set the correct headers to describe that post body. The CURLOPT_RETURNTRANSFER is purely so that the response from the remote server gets placed in $result rather than echoed. If you're sending JSON data with PHP, I hope this might help!

68 thoughts on “POSTing JSON Data With PHP cURL

  1. Hello Lorna,

    I just had the same challenge the other day and got to the same conclusion as your snippet.

    Was fairly well documented on the PHP manual as you also pointed out.

    Thanks for sharing this little gem of knowledge.

    Cheers,
    Peter

  2. Thanks, I tried doing something similar style, but didn't set the header to application/json . I don't remember if it worked or not (it was a quick four liner suggestion to a colleague). But what happens if you forget setting the application/json header ?

    • If you don't set the header correctly, the service you are posting to may not understand what it is that you sent - the exact outcome depends entirely on the service though

      • Thanks Lorna.
        Looking at replies below (and I don't know much about script hijacking), I think I will stick setting application/json in the http-header. And if I am writing a server I will (try) not accept simple plain/text.
        Ohh BTW, I learned a lot from the slides that you linked in this post. I asked my colleague to read slide 39 - 42 for a quick introduction to SOAP. Pretty interesting stuff !

  3. Same thing without curl as a dependency (for the newbies who don't know about the excellent PHP's streams API):

    $data = array('name' => 'Hagrid', 'age' => '36');
    $data_string = json_encode($data);

    $result = file_get_contents('http://api.local/rest/users', null, stream_context_create(array(
    'http' => array(
    'method' => 'POST',
    'header' => 'Content-Type: application/json' . "\r\n"
    . 'Content-Length: ' . strlen($data_string) . "\r\n",
    'content' => $data_string,
    ),
    )));

    • Thanks for adding the streams example, that's nice! Streams are pretty awesome but as you say, they're not as widely used or understood as they should be

    • @zaadjis i tried your code, it works but i had a warning, it does post those json data but it doesn't have a response, the warning is this
      file_get_contents(http://yoursite.com/test.json): failed to open stream: HTTP request failed! HTTP/1.1 500 Internal Server Error

  4. Pingback: Lorna Mitchell Blog: Buchung JSON-Daten mit PHP cURL | PHP Boutique

  5. Actually, you can trim down the request a bit and keep it simple.

    You don't have to specify the content-length. It will be calculated automatically and appended to the headers.

    Also, you don't have to declare the request as a post request explicitly. If you are setting the POSTFIELDS option for curl, curl will convert the request type to POST.

  6. Pingback: Lorna Mitchell’s Blog: POSTing JSON Data With PHP cURL | Scripting4You Blog

  7. Hey Lorna,

    Could you give any examples of any of the discussions you elude to on the topic of accepting POST requests with data in form-format?

    Cheers
    /Matt

  8. Pingback: POSTing JSON Data With PHP cURL | PHP | Syngu

  9. Pingback: Post JSON, XML data With cURL and receive it on other end « TechnoReaders.com

  10. Thank you very much for this post, I've been struggling as a non-programmer to attempt to submit some basic form data to an API and this helped immensely.

  11. hi, i'm a total newbie of posting json, REST services and so on but i need to work out this:
    in order to get a file from a website that needs a login to get it, from within my app i have to post to a REST service this:

    [code]{
    "Username":"String content",
    "Password":"String content"
    }[/code]
    to this url: [code]http://www.***.it/***service/***service/novels/{ID}[/code] where ID is the file id number and etc
    trying with http://username:password@www... works for other services but with this service it get "method not allowed"
    the webmaster of the site didn't answer me about it and i'm really tired cause i'm stuck with the work at this point... anyone can help me, please? thanks
    matteo

    • matteo: it sounds like the service isn't expecting you to POST to that URL, but you'd need to talk to the people who created the service to get more information. Sorry I can't be more help

  12. PHP4 , curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json')); is not working. I can't send the JSON variables in the post method using CURL. IS there any other way to do it?

    • I'm afraid I've never used PHP 4 for this type of thing! I don't know what kind support there is for curl, or what kind of "not working" your example is. I think there was some stream support in PHP 4, so you could research how to create the context you need to POST your content.

      You probably don't need me to tell you that PHP 4 is no longer supported; I must strongly recommend that you upgrade.

  13. Hi LORANAGANE,
    As you explained "how to post JSON data with php CURL". Can you tell me "how to post XML data with php curl."

    thanks in advance.

    Nakul.

  14. Pingback: Robert McGhee » June 12th

  15. hi lorna,

    I tried catching the results on another PHP file, but it returns no results($_POST is empty). Any idea how this should be done?

    • You need to put the URL of the file, as if you were web requesting it, in the curl_init call - and then it will receive the POST vars. Whatever your target file outputs you will get back as the response, so you can debug that way, or use a proxy such as Wireshark or Charles to see what is being sent, or not. Hope that helps!

  16. Pingback: Enviando dados JSON usando cURL | PHP Maranhão

  17. Thanks for posting this. I'd tried a couple of other resources and tried setting curl to send the header that were in-place in the php document however it wasn't working. When I set it up as in your example it started working. :D

  18. Hi Lorna,

    I call a webservice from a JQuery $.getJSON function, it works fine.
    [code]
    var p = {
    'field1': 'value1',
    'field2': 'value2',
    'field3': 'value3'
    };
    $.getJSON('https://service:xxx@xxx.xxx.yyyyy.com.xx/service/search?callback=?', p, function(data) {
    if (data[0]) {
    // print results
    } else {
    // no results found
    }
    });
    [/code]

    I am trying to connect from PHP and CURL, however it does not work, it always return false.
    [code]
    //FIRST TRY
    $params = array( 'field1' => 'value1', 'field2' => 'value2', 'field3'=> 'value3');
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_URL, 'https://service:xxx@xxx.xxx.yyyyy.com.xx/service/search?callback=?');
    curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
    $result = curl_exec($ch); // return false instead my JSON
    // SECOND TRY
    $data_string = json_encode($params);
    $ch = curl_init('https://https://service:xxx@xxx.xxx.yyyyy.com.xx/service/search?callback=?');
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'Content-Type: application/json',
    'Content-Length: ' . strlen($data_string))
    );

    $result2 = curl_exec($ch); // // return false instead my JSON
    [/code]

    What I am doing wrong?

    many thanks,

    • There are a couple of things to check. I don't write much JS but your jquery example looks like it's making a GET request rather than a POST request, so try putting your variables on the end of the URL and using GET from PHP?

      Also try checking if you get anything from curl_error($ch) as if the server has any more information, you will find it here.

      Hope that helps, and good luck!

  19. Hi Lorna
    Based on your code i did the following but it is not working what could be the problem ?

    "Hagrid", "age" => "36");
    //$data_string = json_encode($data);
    $str_obj_json='{
    "method":"SUBMIT","params":{
    "batchType":"submit",
    "batchId":"alvarons",
    "origAddr":"550",
    "origTon":2,
    "userData":"Movistar les desea Feliz Navidad",
    "submits":
    [
    {
    "messId":"mess127_001",
    "destAddr":"51975375377"},
    {
    "messId":"mess127_002",
    "destAddr":"51971855080"}
    ]
    }
    }';
    $ch = curl_init('http://10.10.237.8:21098/SMBULK/BATCH');
    //curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $str_obj_json);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'Content-Type: application/x-www-form-urlencoded',
    'Content-Length: 395',
    'Authorization: Basic dGVzdDp0ZXN0',
    'User-Agent: Wget/1.12 (solaris2.10)',
    'Connection: Keep-Alive',
    'Accept: */*')
    );
    $result = curl_exec($ch);
    ?>

    • Hard to guess from this example but you are sending JSON as the body while setting the Content-Type header to indication a form submission, set that to "application/json" instead and see if that helps?

  20. Very nice, that's just what I was after, no need for all those over the top Libraries for json rpc 2.0

    I hacked it a bit so you can work with posted data like so:

    $json_req['params'] = $myParams;
    $json_req['jsonrpc'] = '2.0';
    $json_req['method'] = 'myMethod';
    $json_req['id'] = 1;
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($json_req));

    Thanks again!

  21. This page contains json data : https://indexes.nasdaqomx.com/Index/Weighting/NBI

    I am trying to scrap that json data using the script :

    $data = array('id' => 'NBI', 'timeOfDay' => 'SOD', 'tradeDate'=> date('Y-m-dTh:i:s.000'));
    $data_string = json_encode($data);

    $ch = curl_init('https://indexes.nasdaqomx.com/Index/WeightingData');
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER , false);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'Content-Type: application/json',
    'Content-Length: ' . strlen($data_string))
    );

    $result = curl_exec($ch);
    if(!$result)
    curl_error($ch);
    else {
    echo "";
    print_r($result);
    exit;
    }
    I am getting the page content but not the json output. Please let me know, where I am wrong.

  22. "CURLOPT_RETURNTRANSFER", this was the exact thing I was looking for to post data to another domain without begin echoed.. came to know by your example. You really saved my day and made my day too.. thanks a lot.

  23. While working with your example, I found that it failed until I changed the JSON conversion line to:
    $data_string = "json=" . json_encode($data) . "&";

    index.php
    ------
    "isInstalled",
    "params" => Array
    (
    "1" => "3",
    "2" => "4",
    )
    );

    $data_string = "json=" . json_encode($data) . "&";
    $ch = curl_init("http://localhose/parrot.php");
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
    $results = curl_exec($ch);

    print ($results);
    ?>
    =====

    parrot.php
    ------

  24. trying to get "post json data via api" to work - going nowhere! basic questions:
    >the URL i am sending the json data to - what should that page do when it is called?
    >what should be on that page? how do i get data there, then calculate using my class, then return the data?
    >i feel lost regarding API's. people post things that seem in the middle of the process. please explain it from the ground up. for hours i view posts that do not really cut to the essence of everything that is going on.
    >i already have an index.html that sets up an array, then instantiates my Calculate class that has methods for Mean, Median, Mode, and Range - that works fine. BUT,
    >how do i "make it available via an API", and provide the input as JSON, and then output a JSON format?

    A more complete explanation is here: "Your client has asked you to make this library available via an API. Your API should implement a single endpoint called "/mmmr" with no query
    string parameters. When a POST request is called to "/mmmr", a single JSON object will be passed with an attribute called "numbers". "numbers" is a JSON array of n numbers that should be processed. The script should process the mean, median, mode and range of the numbers and return back a JSON object."

    Sample JSON POST body to [single endpoint] /mmmr
    [code]
    {
    "numbers": [
    5, 6, 8, 7, 5
    ]
    }
    [/code]
    Sample JSON Return Response from /mmmr
    [code]
    {
    "results": {
    "mean": 6.2,
    "median": 6,
    "mode": 5,
    "range": 3
    }
    }
    [/code]

    • Your page should do:

      $data = json_decode(file_get_contents("php://input"));

      Inspect that and you should be able to see the data that you sent to the script. HTH!

  25. Hi Lorna,
    Here is my code what I did, but it is not working, can you give some explanation?

    $data = array("original_filename"=>$original_filename,"hardware_status"=>$hardware_status,"software_version"=>$software_version,"original_body"=>$original_body,"looqiId"=>$lId,"longitude"=>$lng,"latitude"=>$lat,"battery_voltage"=>$bat,"time_stamp"=>$time_stamp,"_version_"=>$version);

    $data_string = json_encode($data);

    //return $data_string;

    $ch = curl_init('https://looqi-api.movingintelligence.nl/looqireceiver/');

    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'Content-Type: application/json',
    'Content-Length: ' . strlen($data_string))
    );
    curl_setopt($ch, CURLOPT_TIMEOUT, 5);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);

    //execute post
    $response = curl_exec($ch);

    //close connection
    curl_close($ch);

    return $response;

Leave a Reply

Please use [code] and [/code] around any source code you wish to share.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>