144

With PHP, is it possible to send HTTP headers with file_get_contents() ?

I know you can send the user agent from your php.ini file. However, can you also send other information such as HTTP_ACCEPT, HTTP_ACCEPT_LANGUAGE, and HTTP_CONNECTION with file_get_contents() ?

Or is there another function that will accomplish this?

Marcus
  • 4,400
  • 13
  • 48
  • 64

7 Answers7

375

Actually, upon further reading on the file_get_contents() function:

// Create a stream
$opts = [
    "http" => [
        "method" => "GET",
        "header" => "Accept-language: en\r\n" .
            "Cookie: foo=bar\r\n"
    ]
];

// DOCS: https://www.php.net/manual/en/function.stream-context-create.php
$context = stream_context_create($opts);

// Open the file using the HTTP headers set above
// DOCS: https://www.php.net/manual/en/function.file-get-contents.php
$file = file_get_contents('http://www.example.com/', false, $context);

You may be able to follow this pattern to achieve what you are seeking to, I haven't personally tested this though. (and if it doesn't work, feel free to check out my other answer)

Xavi Montero
  • 9,239
  • 7
  • 57
  • 79
Dominic Barnes
  • 28,083
  • 8
  • 65
  • 90
  • 1
    see also: http://docs.php.net/context and http://docs.php.net/stream_context_create – VolkerK Jan 21 '10 at 08:34
  • 21
    this the only useful answer on this page – Gordon Oct 23 '12 at 08:08
  • 12
    I wish more people here would give the actual answer to this question instead of just pointing to the cURL page. Thanks. – mrbellek Dec 17 '12 at 08:15
  • 3
    suddenly curious: what is the **default** user agent of `file_get_contents()`? does it specify one? – Raptor Oct 16 '15 at 08:24
  • 5
    @Raptor `ini_set('user_agent', 'SomeBrowser v42.0.4711');` go to http://user-agent.me and copy yours from there.. or edit php.ini to change it globally – jaggedsoft Oct 28 '16 at 23:29
  • 1
    @NextLocal I was asking for the default value, not assigning value to it – Raptor Oct 31 '16 at 02:21
  • 1
    @Raptor the default user-agent sent by PHP is empty, just a blank string. I changed my `user_agent` in php.ini so I can access pages like Google – jaggedsoft Oct 31 '16 at 18:24
  • Better to use the magic constant PHP_EOL instead of '\r\n' as it is platform/OS independant. If your system doesnt see '\r\n' as a CRLF, then it'll end up just joining the two headers with a literal '\r\n'. – hiburn8 Oct 08 '19 at 13:16
  • should I change `'http' =>` to `'https' =>` for an `https` url? – Soheil Apr 27 '20 at 10:45
  • @Soheil No, this has nothing to do with what your URL looks like. "http" are options for the HTTP protocol. The "https" key holds options for SSL / TLS information, like which certificates to use, whether to check the validity of hostname, and so on. PHP will automatically handle encrypted (https://) URIs. Normally you don't have to add the "https" key at all. – StanE May 20 '23 at 15:45
108

Here is what worked for me (Dominic was just one line short).

$url = "";

$options = array(
  'http'=>array(
    'method'=>"GET",
    'header'=>"Accept-language: en\r\n" .
              "Cookie: foo=bar\r\n" .  // check function.stream-context-create on php.net
              "User-Agent: Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.102011-10-16 20:23:10\r\n" // i.e. An iPad 
  )
);

$context = stream_context_create($options);
$file = file_get_contents($url, false, $context);
halfer
  • 19,824
  • 17
  • 99
  • 186
Fabrice
  • 1,081
  • 1
  • 7
  • 2
  • 8
    You shouldn't impersonate the user agent of a browser. Instead, create a User-Agent string for your tool. http://www-archive.mozilla.org/build/revised-user-agent-strings.html could give some idea about the format. – Dereckson Jan 20 '13 at 05:21
  • 2
    @Vince I think it may work both ways in certain circumstances. Setting the agent header like that, as a string, worked in my case (WAF needed non empty user agent for request to pass) – dhaupin Nov 25 '16 at 14:52
  • 3
    @Vince The [PHP docs state](http://php.net/manual/en/context.http.php) that both can be used and the "User-Agent" `header` will override the `user_agent` array element, if both are specified. – MrWhite Feb 05 '17 at 19:00
  • 1
    NOTE: Never use single quotes with strings containing special characters like \n or \r. PHP will not interpret them correctly and in case of sending headers, your headers will not get sent correctly. – ak93 Mar 31 '18 at 20:54
  • 1
    @Fanky the simplest could be "YourTool/1.0.0". When you release a new version, you can bump the user-agent version too, "YourTool/1.3.5". – Dereckson Apr 15 '19 at 09:53
  • Is the cookie required? Or can that be removed? – Sanjay Manohar May 26 '21 at 22:56
  • copy pasta works for this one – rlatief Jan 17 '22 at 06:40
43

You can use this variable to retrieve response headers after file_get_contents() function.

Code:

  file_get_contents("http://example.com");
  var_dump($http_response_header);

Output:

array(9) {
  [0]=>
  string(15) "HTTP/1.1 200 OK"
  [1]=>
  string(35) "Date: Sat, 12 Apr 2008 17:30:38 GMT"
  [2]=>
  string(29) "Server: Apache/2.2.3 (CentOS)"
  [3]=>
  string(44) "Last-Modified: Tue, 15 Nov 2005 13:24:10 GMT"
  [4]=>
  string(27) "ETag: "280100-1b6-80bfd280""
  [5]=>
  string(20) "Accept-Ranges: bytes"
  [6]=>
  string(19) "Content-Length: 438"
  [7]=>
  string(17) "Connection: close"
  [8]=>
  string(38) "Content-Type: text/html; charset=UTF-8"
}
Janyk
  • 571
  • 3
  • 18
ali_sed
  • 519
  • 4
  • 2
  • 8
    this does not answer the question at all. – Gordon Oct 24 '12 at 08:59
  • 38
    Maybe not, but it answers the opposite question implied in the title, which is how to read the response headers from file_get_contents. And this is where Google lands when investigating THAT question. – Rich Remer Jul 09 '14 at 20:59
  • He is not asking that. He is asking how to post headers with file_get_content – mmoreram Aug 25 '23 at 08:49
0

Using the php cURL libraries will probably be the right way to go, as this library has more features than the simple file_get_contents(...).

An example:

<?php
$ch = curl_init();
$headers = array('HTTP_ACCEPT: Something', 'HTTP_ACCEPT_LANGUAGE: fr, en, da, nl', 'HTTP_CONNECTION: Something');

curl_setopt($ch, CURLOPT_URL, "http://localhost"); # URL to post to
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1 ); # return into a variable
curl_setopt($ch, CURLOPT_HTTPHEADER, $header ); # custom headers, see above
$result = curl_exec( $ch ); # run!
curl_close($ch);
?>
phidah
  • 5,794
  • 6
  • 37
  • 58
  • 6
    The snippet you show is easy to achieve with `file_get_contents` as well and I have yet to come across a Use Case which you can only achieve with cURL. – Gordon Oct 24 '12 at 09:06
  • 1
    Variable $header don't exist, perhaps you meant to write $headers ? Might be worth correcting. – Olindholm Sep 04 '21 at 08:32
0

Yes.

When calling file_get_contents on a URL, one should use the stream_create_context function, which is fairly well documented on php.net.

This is more or less exactly covered on the following page at php.net in the user comments section: http://php.net/manual/en/function.stream-context-create.php

ahmedg
  • 309
  • 1
  • 2
  • 12
Laereom
  • 601
  • 7
  • 12
-3

If you don't need HTTPS and curl is not available on your system you could use fsockopen

This function opens a connection from which you can both read and write like you would do with a normal file handle.

Gordon
  • 312,688
  • 75
  • 539
  • 559
AlexB
  • 726
  • 4
  • 13
  • 2
    yes, but it would also mean the OP has to implement the HTTP protocol by hand. Also, the OP didn't ask about alternatives to `file_get_contents` so this is somewhat of an off-topic answer. – Gordon Oct 24 '12 at 09:02
  • No sense at all – mmoreram Aug 25 '23 at 08:48
-4

Unfortunately, it doesn't look like file_get_contents() really offers that degree of control. The cURL extension is usually the first to come up, but I would highly recommend the PECL_HTTP extension (http://pecl.php.net/package/pecl_http) for very simple and straightforward HTTP requests. (it's much easier to work with than cURL)

Dominic Barnes
  • 28,083
  • 8
  • 65
  • 90