Wez Furlong I am Wez Furlong, Chief Software Architect at Message Systems. We're responsible for building an awesome Messaging Platform.

I'm also a PHP Core developer and OpenSource contributor, residing in Maryland, USA with Juliette, Xander and Lily. (read more)

Subscribe. (circulation 928)
Comments. (circulation 8)

Search powered by Google

HTTP POST from PHP, without cURL

15th November 2006 @ 13:59 EDT

I don't think we do a very good job of evangelizing some of the nice things that the PHP streams layer does in the PHP manual, or even in general. At least, every time I search for the code snippet that allows you to do an HTTP POST request, I don't find it in the manual and resort to reading the source. (You can find it if you search for "HTTP wrapper" in the online documentation, but that's not really what you think you're searching for when you're looking).

So, here's an example of how to send a POST request with straight up PHP, no cURL:

<?php
  function do_post_request($url, $data, $optional_headers = null)
  {
     $params = array('http' => array(
                  'method' => 'POST',
                  'content' => $data
               ));
     if ($optional_headers !== null) {
        $params['http']['header'] = $optional_headers;
     }
     $ctx = stream_context_create($params);
     $fp = @fopen($url, 'rb', false, $ctx);
     if (!$fp) {
        throw new Exception("Problem with $url, $php_errormsg");
     }
     $response = @stream_get_contents($fp);
     if ($response === false) {
        throw new Exception("Problem reading data from $url, $php_errormsg");
     }
     return $response;
  }

$optional_headers is a string containing additional HTTP headers that you would like to send in your request.

PHP's HTTP wrapper will automatically fill out the Content-Length header based on the length of the $data that you pass in. It will also automatically set the Content-Type to application/x-www-form-urlencoded if you don't specify one in the $optional_headers.

I find this very handy; I don't need to code in redirection logic, HTTP auth handling, user agent setting and so on; they are handled for me by PHP.

You may also want to look into http_build_query() which is a convenience function that allows you to assemble query/post parameters from a PHP variable, applying appropriate escaping.

Kudos to Sara Golemon for both of these things. You can find more documentation on the HTTP wrapper options in the HTTP and HTTPS page in the PHP manual.

by Wez Furlong in .
Post a comment

Sending binary data

22nd January @ 05:01 EDT

Great code! But was wondering, how do I send binary data, such as an image?

by john in .

Re: POST example on php.net

8th February @ 23:59 EDT

Thank Roland!

This script works quite well, and is avoids the memory leak issue.

Bruno

by Bruno in .

Thanks!

22nd February @ 20:10 EDT

Thanks for this script!

I used it along with a few hundred lines of test data in a script to test a form that I built. The script worked great!!!

by Jabari in .

Simplifying

15th November 2006 @ 17:40 EDT

You could further simplify the code by file file_get_contents() rather then fopen, (get data) fclose.

I get errors?

27th June 2007 @ 18:02 EDT

Parse error: parse error, unexpected T_NEW in /home/web_dev/www/passgomedia.com/HOHO.php on line 17

??

by myspace.com/mrbunsen in .

cool!

13th September 2007 @ 19:22 EDT

thanks dude, that code really got me on to the right track, creating a XML-RPC compilant blog autopinger!

by coops.se in .

Alternative to stream_get_contents?

22nd September 2007 @ 19:59 EDT

I'm stuck on PHP 4.3 so unfortunately I'm not able to get this working because stream_get_contents is PHP 5.

Is there an alternative I can use? I tried fpassthru() and it did not seem to work right.

by Randy Whitaker in .

PHP4 Alternative

9th October 2007 @ 11:39 EDT

A PHP4 alternative (if it exists) would be really nice!

by Raam in .

A PHP 4 alternative

5th December 2007 @ 11:15 EDT

I wrote a PHP 4 alternative which you can see here:

http://www.enyem.com/wiki/index.php...T_request_(PHP)

by Csaba in .

Cool app

12th December 2007 @ 07:04 EDT

<a href="http://madhuri-dixit.110mb.com">Madhuri Dixit</a> likes this cool tutorial. Madhuri was previously using cURL. Now Dixit will do it with vanilla PHP

by Madhuri Dixit in .

$data

15th December 2007 @ 20:13 EDT

I don't understand what we have to put into $data, I tried some requests like:

$data = "name1=info1&name2=info2$name3=info3";

But it doesn't work... what do we have to do?

by Jack Leblanc in .

$data and redirect

19th January 2008 @ 07:50 EDT

Hi,

Same as Jack, I'm not sure what to put in $data, is it just an array or http_build_query()?

Another question, will the function redirect the page to new url?

by Welly Lee in .

Hi

5th February 2008 @ 14:15 EDT

Hey Wez, are you the dr. Evil from http://www.hatebook.org?

by http://www.amorliber.com in .

$data

21st March 2008 @ 23:24 EDT

Try this for the data:

$data = array ('username' => $username, 'first_name' => $first_name, 'last_name' = $last_name);

$data = http_build_query($data);

by spatical.com in .

HTTPS

21st April 2008 @ 03:34 EDT

Hey...

Could someone please help me with HTTPS POST request?

What changes do I need to make to change a request from HTTP to HTTPS?

by Sumedh Inamdar in .

Content-Type

22nd July 2008 @ 22:19 EDT

Hi,

I am using the script to try and interact with the Google Calendar API which requires the content type to be set as "application/atom+xml".

I have used the option headers parameter to try and do this, but the response coming back from Google is claiming the Content-Type is "application/x-www-form-urlencoded".

How should I be adding the information to the headers parameter correctly? I have tried using an array ($Headers = Array('Content-Type'=> 'application/atom+xml');) and also just entering the string "Content-Type: application/atom+xml" with no luck.

Any ideas where I could be going wrong?

by Andrew in .

restrieving the returned data?

27th September 2008 @ 09:07 EDT

Hi,

Awesome function... just one thing... may be a dumb question but how do I retrieve the response as a variable to work with.

ie. (This is just the end of my code)

<?php
 
echo do_post_request($url, $prepd_data);
echo("Status = " . $response['Status']);
 
?>

The data that I'm requesting is returning fine and always contains a 'Status' value, which you can see I'm trying to get hold of in the above code. Above I'm trying '$response' but it's not working.

If you can see what I'm trying to explain, anyone have any help?

Thanks

by Helen in .

HTTPS

3rd February 2009 @ 10:34 EDT

The same as Sumedh Inamdar, will HTTPS work too?

by Anonymous in .

HTTP retriever library

12th February 2009 @ 11:35 EDT

Here is a library that is working using php4 HTTP POST and GET.

sample code included.

Tested, OK.

<a href="http://www.phpclasses.org/browse/package/3105.html" title="HTTP retriever class">http://www.phpclasses.org/browse/package/3105.html</a>

by petyus in .

https post help

14th April 2009 @ 11:58 EDT

Hi Wez,

I've seen your 'http post' code in many sites, but I'm having a hard time implementing it myself.

Could you please provide a usage example ?

Specifically the code keeps throwing the first exception and I don't understand why or how to fix it..

Thanks in advance.

by Joe in .

$php_errormsg

11th June 2009 @ 19:40 EDT

What is $php_errormsg? It doesn't seem to be set anywhere and it's not some magic PHP variable either. So how do I know exactly what the errors that are being thrown are?

by Daevid Vincent in .

$php_errormsg

11th June 2009 @ 21:25 EDT

Daevid, you need to work on those search skills.

Go to php.net, search the online documentation for php_errormsg and you find this:

http://www.php.net/manual/en/reserv...phperrormsg.php

HTTPS

11th June 2009 @ 21:26 EDT

Yes, if you have the openssl extension loaded, you should be able to use the same trick for HTTPS.

don't suppress warnings

12th June 2009 @ 06:56 EDT

Better leave out the @ before fopen and stream_get_contents, as this suppresses HTTP 500 'warnings'.

by Anonymous in .

Works beautifully

24th June 2009 @ 07:19 EDT

I'm using this when simple_xml_loadfile fails because the $_GET data is too long. Works a treat.

Example usage:

$data = array ('code' => 'tpsadd', 'id' => $id, 'text' => $tpsnumbers);

$data = http_build_query($data);

$url = 'http://' . XML_SERV0 . '/xml/ukpb_corp';

do_post_request($url, $data);

by Jamie in .

remote post

26th June 2009 @ 10:37 EDT

If I use this script on my web server, I am able to post to other pages on my web server just fine!

BUT when I put the same exact script on my localhost server and try to post to my web server, the post request reaches the post target page but does not pass on variables.

Why is this?

Thanks for the script! I'm sure a few tweaks later, we'll have it working!

by scott harper in .

Go to url, instead of getting

17th July 2009 @ 08:36 EDT

Hi

I am trying to go to another url using your script, but I cant figure out how to make the changes.

The goal is to redirect my visitor to another url with the post values hidden. Can you give me a hint?

Thanks!

Fredric

by F. Fohlin in .

HTTP POST

21st July 2009 @ 06:09 EDT

PH P's HTTP wrapper will automatically fill out the Content-Length header based on the length of the $data that you pass in. It will also automatically set the Content-Type to application/x-WWW-form-URL encoded if you don't specify one in the $optional_headers. I have used the option headers parameter to try and do this, but the response coming back from Google is claiming the Content-Type is "application/x-WWW-form-URL encoded"......

http://www.roulette-gambling-site.com

by kimi sha in .

POST example on php.net

26th July 2009 @ 08:21 EDT

I saw another example posted on php.net, which seemed to be quite a pretty solution, at the page introducing the "HTTP context options"

http://www.php.net/manual/en/context.http.php

<?php
 
$postdata = http_build_query(
    array(
        'var1' => 'some content',
        'var2' => 'doh'
    )
);
$opts = array('http' =>
    array(
        'method'  => 'POST',
        'header'  => 'Content-type: application/x-www-form-urlencoded',
        'content' => $postdata
    )
);
$context  = stream_context_create($opts);
$result = file_get_contents('http://example.com/submit.php', false, $context);
 
?>

by Roland in .

#

27th July 2009 @ 15:46 EDT

Hello. I think this article is very interesting. I think that your post about HTTP POST from PHP, without cURL is really good. I will try it and tell you how it show up.

<a href="http://www.leodata.de/webdesign">

Webdesign Stuttgart

</a>

by Anonymous in .

fopen memory leaks

19th September 2009 @ 19:27 EDT

Really interesting technique. However, there is a pretty serious memory leak in fopen in php5. Making many of these requests during the lifetime of a script will definitely cause you to run out of memory.

Check out the bug here :

http://bugs.php.net/bug.php?id=32255

It's a fairly old bug, but it still seems to be open. A quick test on a server running 5.2.8 confirms that the leak is still there. Using this beats cURL in readability and succinctness, but it needs to be used with caution!

by Chris Henry in .

help me, I am so close.

4th November 2009 @ 22:09 EDT

I am using a switch statement to error check an included form. When it passes I am trying to use your beuty to pass it on to a url. The trick is the url requires

<form action='http://crm.zoho.com/crm/WebToContactForm' method='POST' onSubmit='javascript:document.charset="UTF-8";' accept-charset='UTF-8'>

Here is what I got, can you help?

I didn't clean up the spacing yet cause I am just trying to get it to work.

<?
                switch($_GET[action]) {
                    //error checking for required fields
                    case "check";
                        if(strlen($_POST[bussiness_name]) > 0 && strlen($_POST[contact_name]) > 0 && strlen($_POST[email]) > 0 && strlen($_POST[phone]) > 0 && strlen($_POST[address]) > 0 && strlen($_POST[zip]) > 0 && strlen($_POST[planyear]) > 0) { 
                        //post function
                            $url="path";
                            $data="";
                            $data.="";
                            $data.="";
                            $data.="";
                            $data.="First Name=$_POST[contact_name]\n";            
                            $data.="Phone=$_POST[phone]";
                            $data.="Email=$_POST[email]";
                            function do_post_request($url, $data, $optional_headers = null)
  {
     $params = array('http' => array(
                  'method' => 'POST',
                  'content-type' => 'text/html',
                  'charset' => 'UTF-8',
                  'content' => $data
               ));
     if ($optional_headers !== null) {
        $params['http']['header'] = $optional_headers;
     }
     $ctx = stream_context_create($params);
     $fp = @fopen($url, 'rb', false, $ctx);
     if (!$fp) {
        throw new Exception("Problem with $url, $php_errormsg");
     }
     $response = @stream_get_contents($fp);
     if ($response === false) {
        throw new Exception("Problem reading data from $url, $php_errormsg");
     }
     return $response;
  }
                            print "<br> Thank-you for contacting us regarding your event.  We will be in touch soon.";
                        } else {
                            print " <span style='color: #e65a05;'><b>You did not fill out all of the required fields.  Please fill out and resubmit.</b></span>";
                            include("groupform.inc.php");
                        }
                    break;
                    default:
                        include("groupform.inc.php");
                    break;
                }
                ?>

oh geeze

4th November 2009 @ 22:33 EDT

nm. such a noob.

$optional_headers=header("Content-type: text/html; charset=utf-8");
Post a comment

Would you like to work with me?
I have positions open for server/infrastructure software development (C) and QA.

Ohloh profile for wez