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.

EDIT: A more modern take on this topic is here http://www.lornajane.net/posts/2018/make-a-post-request-from-php-with-guzzle

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!

107 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,
    ),
    )));

  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:[email protected]/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:[email protected]/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:[email protected]/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;

  26. $url = ‘http://localhost/phalcon-api-oauth2/insertposts/’;

    //Initiate cURL.
    $ch = curl_init($url);

    $atoken=’wCtmX4HC94yACOLVJVtufqG5C41RcbFHkq5wq2u4′;

    $jsontoken= array(‘token’ => ‘wCtmX4HC94yACOLVJVtufqG5C41RcbFHkq5wq2u4’);

    $jsonTokenEncoded = json_encode($jsontoken);

    curl_setopt($ch, CURLOPT_HTTPHEADER,$jsontoken);

    //The JSON data.
    $jsonData = array(
    // ‘token’ => ‘wCtmX4HC94yACOLVJVtufqG5C41RcbFHkq5wq2u4’,
    ‘name’ => ‘O345345’,
    ‘type’ => ‘mechanicalss’,
    ‘year’ => ‘1983’
    );

    //Encode the array into JSON.
    $jsonDataEncoded = json_encode($jsonData);

    //Tell cURL that we want to send a POST request.
    curl_setopt($ch, CURLOPT_POST, 1);

    //Attach our encoded JSON string to the POST fields.
    curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonDataEncoded);

    //Set the content type to application/json
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(‘Content-Type: application/json’));

    //Execute the request
    echo $result = curl_exec($ch);

    I m using this but i m getting this error. The request is missing an access token in either the Authorization header or the token request parameter.Please help

  27. Lornajane,

    Thanks for this article.

    Do you think all or part of a JSON string should be url encoded before posting as in your example?

    I expect not. I would like to hear your reasoning.

    Thanks,

    Toney

    • I don’t think a JSON string should be URL encoded for POSTing, because it’s not being passed in the URL; when you POST it goes into the body of the request so it will arrive safely without encoding. Hope that helps!

  28. $data = array(“score” => “234”, “playerName” => “Noman”, “cheatMode” => “false”);
    $data_string = json_encode($data);
    var_dump($data_string);
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, “https://www.parse.com/apps/testapp–6335/collections”);
    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(
    ‘X-Parse-Application-Id:G1S3htqkA*******O0Lvw8IRKf7IeaNB5jY64’,
    ‘X-Parse-REST-API-Key:KQxLUo4sXAh7D*****IdTP3Lxl6YzT6o2jN’,
    ‘Content-Type: application/json’
    ));
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    $result = curl_exec($ch);
    var_dump($result);

    But i got error
    SSL certificate problem: unable to get local issuer certificate

  29. Thanks for the notice on
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    ‘Content-Type: application/json’,
    ‘Content-Length: ‘ . strlen($contents))
    );
    It seems that was the issue I was fighting. My server was giving error code 400 malformed for a while before switching that in.

  30. i am using above the code but it showing

    HTTP Status 404 – Not Found

    type Status report

    message Not Found

    description The requested resource is not available.

    Apache Tomcat/7.0.61

  31. Hello Lorna,

    Your blog was extremely helpful, I would like to thank you for that. I have a small problem.

    I am communicating with web service for adding and updating an element, and on localhost, it works perfectly fine, but on the live server, it is giving me a status 0 error. For adding and updating an element, I am associating a port number with the web service URL. Here is my code.

    $ch = curl_init(‘http://int.otono-me.com:8999/api/customers/new’);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch, CURLOPT_FAILONERROR, 1);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, “PUT”);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_TIMEOUT, 50);
    curl_setopt($ch, CURLOPT_PORT, 8999);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    “Content-Type: application/json”,
    “X-Auth-Token: ” . $_SESSION[“Token”]
    ));

    $result = curl_exec($ch);
    $curl_errno = curl_errno($ch);
    $curl_error = curl_error($ch);
    if($curl_errno > 0) {
    echo “cURL Error ($curl_errno): $curl_error\n”;
    } else {
    echo “Successful\n”;
    }
    curl_close($ch);

    echo $result;

    On Localhost, the above code works perfectly fine, but on the live server, I get this error:

    cURL Error (7): connect() timed out!

    Do I need to make certain changes in the above code to ensure that it works with on the live server?

    Looking forward for your response,

    Thank you,

    Mandar CHITALE

    • If the code works on one platform but not on live, it’s most likely that you need to request outgoing network access from the live server; it’s not unusual for this to be disabled.

  32. Pingback: How to use PHP curl GET and POST with JSON web services | p6abhu

  33. Thanks, this site was a big help. I was using a product manual without PHP examples, and found that using CURLOPT_HTTPGET and CURLOPT_POST were not working, but when I used the CURLOPT_CUSTOMREQUEST, I got things to work. I’m NOT a big fan of JSON.

  34. Very helpful. I was a bit confused about how the content length for post data works and your explanation really helped.
    Many thanks and great to see that many of your resources have really aged well!

  35. $data = array(‘params’=>$params,”action”=>$action); // fire url
    $data_json = json_encode($data,JSON_FORCE_OBJECT);
    $url = $fireArr[0].”/cgi-bin/json_xfer”;
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
    curl_setopt($ch, CURLOPT_USERPWD, $logdetail);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(‘Content-Type: application/json’));
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS,$data_json);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

    $dmpresponse = $resp = curl_exec($ch);
    curl_close($ch);

    i am using above the code but it showing

    But i am getting ” Method Not Allowed”

    • That’s a response from the server, it doesn’t allow POST requests to the URL you’re specifying so that 405 “Method not allowed” response tells you that this verb and URL combination aren’t supported.

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.