Fix HTTP 403 Forbidden, Failed to Open Stream – PHP Copy function

Updated on September 1, 2017

I wrote a simple PHP program to copy an image from a website to local directory. The copy() function will copy a file to the specified destination and it can be used to copy a file that’s stored locally and also from a remote website. But I was stuck with an error “failed to open stream HTTP 403 Forbidden”. This tutorial will explain how to fix HTTP 403 Forbidden error while using PHP’s copy function.

php-copy-failed-open-stream

Below is the example to copy a file:

<?php
 $file = 'test.txt';
 $newfile = 'sample.txt';
 if (!copy($file, $newfile)) {
 echo "Unable to copy $file...\n";
 }
 ?>

Similarly, the copy function can be used to copy an image from a website as shown below (copy.php):

<?php
 $imageURL = "https://www.domain.net/images/commercial-wordPress-theme1.jpg";
 copy($imageURL,'sample.jpg');
 ?>
$ php copy.php

Executing the above program will download the image from a given URL and saves it in local directory. And this works because, the web server accepted the request even though the script was executed from a command-line (Non-browser environment where there’s no User-agent is specified).

But not all websites will allow a non-browser environment to access a resource from their web server. For instance, if the web server is configured to check for an User-agent that makes a request, then the above script will fail with an error as shown below:

$ php copy.php
PHP error: copy(https://www.domain.net/images/commercial-wordPress-theme1.jpg): failed to open stream: HTTP request failed! HTTP/1.0 403 Forbidden

The above PHP file was executed in the command-line, so no User-agent would be sent in the header. Hence, the remote web server returned “403 Forbidden” error.

How to Fix HTTP 403 Forbidden, Failed to Open Stream

In order to fix this error, HTTP header should be sent with a fake User-agent as shown below:

$context = stream_context_create(array(
 'http' => array(
 'header' => array('User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; rv:2.2) Gecko/20110201'),
 ),
 ));

Lookout for ‘stream_context_create‘ function, which allows to create and return a stream context. The function will take an associative array as argument in the below format:

$arr['wrapper']['option'] = $value

Here’s the list of available wrappers and options for HTTP context.

  • method string : HTTP methods such as GET, POST etc..
  • header array or string: To send additional headers during the request
  • user_agent string: To send an User-agent
  • content string: To send additional content after the headers
  • proxy string: URI of the proxy server
  • request_fulluri boolean: When set to true, the entire URI will be used while constructing the request.
  • follow_location integer: To follow location header redirects
  • max_redirects integer: Specify the maximum number of redirects
  • protocol_version float: HTTP protocol version
  • timeout float: Timeout for the request
  • ignore_errors boolean: Failure status codes

Well, we are worried about the user_agent option – so use a stream_context_create to send a fake user_agent with the header. Finally, pass the created context string to the copy function as shown below:

<?php
 $context = stream_context_create(array(
 'http' => array(
 'header' => array('User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; rv:2.2) Gecko/20110201'),
 ),
 ));
 $imageURL = "https://www.domain.net/images/commercial-wordPress-theme1.jpg";
 copy($imageURL,'sample.jpg', $context);
 ?>

Now the above program should make a copy of the image that’s hosted on domain.net.

Was this article helpful?

Related Articles

Comments Leave a Comment

Leave a Comment