194

I am calling a series of links using the file_get_contents() method in a loop. Each link may take more than 15 minutes to process. Now, I worry about whether PHP's file_get_contents() has a timeout period?

If yes, it will time out with a call and move to next link. I don't want to call the next link without the prior one finishing.

So, please tell me whether file_get_contents() has a timeout period. The file which contains the file_get_contents() is set to set_time_limit() to zero (unlimited).

4

6 Answers 6

358

The default timeout is defined by default_socket_timeout ini-setting, which is 60 seconds. You can also change it on the fly:

ini_set('default_socket_timeout', 900); // 900 Seconds = 15 Minutes

Another way to set a timeout, would be to use stream_context_create to set the timeout as HTTP context options of the HTTP stream wrapper in use:

$ctx = stream_context_create(array('http'=>
    array(
        'timeout' => 1200,  //1200 Seconds is 20 Minutes
    )
));

echo file_get_contents('http://example.com/', false, $ctx);
3
  • 10
    Can you give info about how to set timeout for https url?
    – Vinay
    Commented May 29, 2013 at 13:35
  • 11
    this thing is not working perfectly, if your value is 1200, its actually is 2400. i just test it.
    – TomSawyer
    Commented Oct 26, 2013 at 15:46
  • 22
    default_socket_timeout, stream_set_timeout, and stream_context_create timeout are all the timeout of every line read/write, not the whole connection timeout.
    – diyism
    Commented Nov 4, 2014 at 8:27
42

As @diyism mentioned, "default_socket_timeout, stream_set_timeout, and stream_context_create timeout are all the timeout of every line read/write, not the whole connection timeout." And the top answer by @stewe has failed me.

As an alternative to using file_get_contents, you can always use curl with a timeout.

So here's a working code that works for calling links.

$url='http://example.com/';
$ch=curl_init();
$timeout=5;

curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);

$result=curl_exec($ch);
curl_close($ch);
echo $result;
4
  • 2
    This answer gives another approach to controlling the connect timeout (using fsockopen instead of curl): stackoverflow.com/a/3690321/1869825
    – stevo
    Commented Apr 7, 2015 at 19:51
  • 2
    you should set both CURLOPT_CONNECTTIMEOUT and CURLOPT_TIMEOUT in curl. See stackoverflow.com/a/27776164/1863432
    – bhelm
    Commented May 2, 2016 at 13:36
  • 3
    Is not a valid response, the question is for "file_get_contents". The response is great but inapropiate.
    – e-info128
    Commented Mar 23, 2019 at 21:38
  • @e-info128 since there is no way do it directly with file_get_contents, this answer is perfectly valid.
    – vanowm
    Commented May 24 at 0:55
38

Yes! By passing a stream context in the third parameter:

Here with a timeout of 1s:

file_get_contents("https://abcedef.com", 0, stream_context_create(["http"=>["timeout"=>1]]));

Source in comment section of https://www.php.net/manual/en/function.file-get-contents.php

HTTP context options:

method
header
user_agent
content
request_fulluri
follow_location
max_redirects
protocol_version
timeout

Non HTTP stream contexts

Socket
FTP
SSL
CURL
Phar
Context (notifications callback)
Zip
1
  • 7
    The timeout given in stream_context_create only works for connection timeout. If the server replies (sends some data) within the given timeout, but takes forever to send the rest of its payload, this timeout doesn't interrupt the slow transfer.
    – z80crew
    Commented Apr 22, 2020 at 12:43
7

It is worth noting that if changing default_socket_timeout on the fly, it might be useful to restore its value after your file_get_contents call:

$default_socket_timeout = ini_get('default_socket_timeout');
....
ini_set('default_socket_timeout', 10);
file_get_contents($url);
...
ini_set('default_socket_timeout', $default_socket_timeout);
4
  • 1
    but you know that ini_set doesn't set the things permanently, right? so basically 4 half of your script is just useless Commented Mar 3, 2019 at 15:02
  • 3
    @FlashThunder Not if there is another call to file_get_contents later in the code that requires the previous timeout. Restoring settings changed on the fly for a specific bit of code after that code has executed is generally good practice. Commented Mar 13, 2019 at 12:38
  • 2
    @FlashThunder it is good practice to restore the socket_timeout value after a call so that subsequent calls to the same function in the same script execution use global settings. Commented Aug 8, 2019 at 14:14
  • 1
    isn't it better to use ini_restore('default_socket_timeout'); instead? php.net/manual/en/function.ini-restore.php Commented Feb 7, 2021 at 15:07
1

For me work when i change my php.ini in my host:

; Default timeout for socket based streams (seconds)
default_socket_timeout = 300
-2

For prototyping, using curl from the shell with the -m parameter allow to pass milliseconds, and will work in both cases, either the connection didn't initiate, error 404, 500, bad url, or the whole data wasn't retrieved in full in the allowed time range, the timeout is always effective. Php won't ever hang out.

Simply don't pass unsanitized user data in the shell call.

system("curl -m 50 -X GET 'https://api.kraken.com/0/public/OHLC?pair=LTCUSDT&interval=60' -H  'accept: application/json' > data.json");
// This data had been refreshed in less than 50ms
var_dump(json_decode(file_get_contents("data.json"),true));
9
  • never ever do that. Aside of opening a bunch of potential security holes, depending on context, you have a full curl API in every PHP installation.
    – John
    Commented Jan 2, 2021 at 16:02
  • I do that all the time since years for my personal scripts, and this has never cause issues. The key part is the -m param. Security holes, only if using unsanitized user data, as warned. This is btw the sole one liner that fully works on all this answers. Read again.
    – NVRM
    Commented Jan 2, 2021 at 22:51
  • PHP doesn't have curl built-in unlike what you are believing, you have to install the separated package php-curl. But shell curl is always available.
    – NVRM
    Commented Jan 2, 2021 at 23:06
  • The PHP environment of anyone asking this question does have libcurl available, anyone who doesn't probably doesn't need to ask that question. Using such shell executions is the dirtiest way you could write something.
    – John
    Commented Jan 3, 2021 at 0:45
  • 2
    I don't think it's dirty, sometimes using the shell is the only way to access a third party module/program.
    – Marco
    Commented Nov 23, 2021 at 18:12

Not the answer you're looking for? Browse other questions tagged or ask your own question.