154

How can I do a RAW POST in PHP using cURL?

Raw post as in without any encoding, and my data is stored in a string. The data should be formatted like this:

... usual HTTP header ...
Content-Length: 1039
Content-Type: text/plain

89c5fdataasdhf kajshfd akjshfksa hfdkjsa falkjshfsa
ajshd fkjsahfd lkjsahflksahfdlkashfhsadkjfsalhfd
ajshdfhsafiahfiuwhflsf this is just data from a string
more data kjahfdhsakjfhsalkjfdhalksfd

One option is to manually write the entire HTTP header being sent, but that seems less optimal.

Anyway, can I just pass options to curl_setopt() that say use POST, use text/plain, and send the raw data from a $variable?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
The Unknown
  • 19,224
  • 29
  • 77
  • 93

2 Answers2

281

I just found the solution, kind of answering to my own question in case anyone else stumbles upon it.

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL,            "http://url/url/url" );
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt($ch, CURLOPT_POST,           1 );
curl_setopt($ch, CURLOPT_POSTFIELDS,     "body goes here" ); 
curl_setopt($ch, CURLOPT_HTTPHEADER,     array('Content-Type: text/plain')); 

$result = curl_exec($ch);
danronmoon
  • 3,814
  • 5
  • 34
  • 56
The Unknown
  • 19,224
  • 29
  • 77
  • 93
  • 4
    will php set the content-length header for you or should you set that as well? – Eric Bloch Jul 13 '13 at 03:47
  • 3
    I cannot get this to work at all. I have a page that I am trying to post raw data to. That page records all raw data it receives into a database table. There are no new rows at all. Do you know if anything has changed here since '09? – James Oct 24 '13 at 13:50
  • 1
    This works for me, without specifying any HTTP header. – xryl669 Jan 14 '14 at 10:27
  • 15
    I just realized that **body goes here** can include any valid json string. – shasi kanth Jul 31 '15 at 07:40
  • To post RAW **files** instead of a variable's contents, see this answer: http://stackoverflow.com/questions/15508850/how-to-raw-post-huge-xml-file-with-curl-php/31696809#31696809 This is especially useful for huge files because `file_get_contents()` won't help. – Shadocko Jan 15 '16 at 08:13
  • 2
    There is a 2G limit for this raw post. If you attempt to send file larger than 2G they will be truncated back to 2G. Its a limitation of the string type being loaded. – Kaden Yealy Aug 30 '16 at 19:06
  • what is the type of `$result` as in what do we expect to see when success/failure – Biasi Wiga Nov 29 '19 at 19:56
  • @BiasiWiga the `$result` is what ever the page is returning. generally you would hope to see a 200 response code at least to know it went through. – Craig B Aug 10 '20 at 06:27
  • is there a way to just write a raw request in its entirety without curl constructing it for us? – Brad Mar 29 '22 at 06:06
  • For me this is what worked, in "body goes here" I just included the json_decode($body) output and perfect response. I did that before but with json content-type it wouldn't work at all. – cdsaenz Sep 29 '22 at 13:38
9

Implementation with Guzzle library:

use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;

$httpClient = new Client();

$response = $httpClient->post(
    'https://postman-echo.com/post',
    [
        RequestOptions::BODY => 'POST raw request content',
        RequestOptions::HEADERS => [
            'Content-Type' => 'application/x-www-form-urlencoded',
        ],
    ]
);

echo(
    $response->getBody()->getContents()
);

PHP CURL extension:

$curlHandler = curl_init();

curl_setopt_array($curlHandler, [
    CURLOPT_URL => 'https://postman-echo.com/post',
    CURLOPT_RETURNTRANSFER => true,

    /**
     * Specify POST method
     */
    CURLOPT_POST => true,

    /**
     * Specify request content
     */
    CURLOPT_POSTFIELDS => 'POST raw request content',
]);

$response = curl_exec($curlHandler);

curl_close($curlHandler);

echo($response);

Source code