PHPackages                             inphinit/proxy - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. inphinit/proxy

ActiveLibrary[HTTP &amp; Networking](/categories/http)

inphinit/proxy
==============

Lib for create web proxy with CORS

2.0.0-rc.3(1mo ago)137478MITPHPPHP &gt;=5.4.0

Since May 11Pushed 1mo ago16 watchersCompare

[ Source](https://github.com/inphinit/inphinit-php-proxy)[ Packagist](https://packagist.org/packages/inphinit/proxy)[ RSS](/packages/inphinit-proxy/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (4)DependenciesVersions (9)Used By (0)

[![Total Downloads](https://camo.githubusercontent.com/919f40601c052a6b7c51d9bf2fa406c093dc9be31c8c52a8bf9c3dd0eb05dc65/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f696e7068696e69742f70726f7879)](https://packagist.org/packages/inphinit/proxy)[![Latest Stable Version](https://camo.githubusercontent.com/bc4dd076068c3582e17c365a001821fa00776aff2570f2b1c160497398b54223/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f696e7068696e69742f70726f7879)](https://packagist.org/packages/inphinit/proxy)[![License](https://camo.githubusercontent.com/5c70cbfa38d377e71cb94290a8c6a83e88abc0c0f8ad5d75ef5e00ca694ab5bc/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f696e7068696e69742f70726f7879)](https://packagist.org/packages/inphinit/proxy)

About Inphinit Proxy
--------------------

[](#about-inphinit-proxy)

Inphinit Proxy is a lightweight PHP proxy library designed to work with html2canvas or other client-side applications that need to bypass CORS restrictions.

Until version 1.x, this project was mainly a proxy solution for *html2canvas*. Starting from version 2.0, it evolved with extensive configuration and customization options, making it suitable for many different use cases.

Although developed as part of the *Inphinit framework*, this library is fully standalone and compatible with any framework — or even plain PHP.

While fully standalone, this library was originally part of the Inphinit framework. If you’re starting a new project, consider adopting the framework itself. For more details:

Proxies for other scripting languages
-------------------------------------

[](#proxies-for-other-scripting-languages)

If you're not using PHP but still need a proxy for *html2canvas*, check out the following implementations:

- [html2canvas proxy for ASP.NET (csharp)](https://github.com/brcontainer/html2canvas-csharp-proxy)
- [html2canvas proxy for Classic ASP (vbscript)](https://github.com/brcontainer/html2canvas-asp-vbscript-proxy)
- [html2canvas proxy for Python (Works with any framework)](https://github.com/brcontainer/html2canvas-proxy-python)

Requirements
------------

[](#requirements)

1. Recommended: *PHP 8* (see the currently supported versions at )
    - Minimum: *PHP 5.4* (backward compatibility is preserved for environments with upgrade limitations)
2. cURL PHP extension to use the `CurlDriver`
3. `allow_url_fopen` must be set to `1` on `php.ini` to use `StreamDriver`

Installing
----------

[](#installing)

You can install via composer:

```
composer require inphinit/proxy
```

Then include this in your script or controller:

```
use Inphinit\Proxy\Proxy;
use Inphinit\Proxy\Drivers\CurlDriver;
use Inphinit\Proxy\Drivers\StreamDriver;

$proxy = new Proxy();

// Set drivers used for download
$proxy->setDrivers([
    CurlDriver::class,
    StreamDriver::class
]);

try {
    // Execute download
    $proxy->download($_GET['url']);

    // Display raw output
    $proxy->response();
} catch (Exception $ee) {
    $code = $ee->getCode();
    $message = $ee->getMessage();

    echo 'Error: (', $code, ') ', $message;
}
```

If you're not using a framework, you can download the release from , then extract it, move it to your web server, and optionally rename the folder, for example:

```
mv inphinit-php-proxy-2.0.0 proxy
```

Configure html2canvas
---------------------

[](#configure-html2canvas)

If you are using a web framework, simply point to the address of the route you configured to use the proxy, for example:

```
html2canvas(document.getElementById('container'), {
    logging: true,
    proxy: '/proxy'
}).then((canvas) => {
    canvas.toBlob((blob) => { });
});
```

If you have manually downloaded it to use on your server, you can use the `proxy.php` script, an example:

```
html2canvas(document.getElementById('container'), {
    logging: true,
    proxy: '/proxy/proxy.php'
}).then((canvas) => {
    canvas.toBlob((blob) => { });
});
```

API Methods
-----------

[](#api-methods)

MethodDescription`setMaxDownloadSize(int $value): void`Set the maximum allowed download size`getMaxDownloadSize(): int`Get the maximum allowed download size`setMaxRedirs(int $value): void`Set the maximum number of HTTP redirects`getMaxRedirs(): int`Get the maximum number of HTTP redirects`setReferer(string $value): void`Set the `Referer` request header`getReferer(): string`Get the `Referer` request header`setTimeout(int $value): void`Set the connection timeout in seconds`getTimeout(): int`Get the connection timeout in seconds`setUserAgent(string $value): void`Set the `User-Agent` request header`getUserAgent(): string`Get the `User-Agent` request header`setDrivers(array $drivers): void`Set the list of driver class names used for downloading resources`setControlAllowOrigin(string $origin): void`Set the `Access-Control-Allow-Origin` header`setControlAllowHeaders(array $headers): void`Set the list of allowed headers`setOptions(string $key, mixed $value): void`Set generic options`getOptions([string $key]): mixed`Get generic options`getOptionsUpdate(): int`Returns an internal incremental counter used to determine whether driver options have changed`setAllowedUrls(array $urls): void`Set the list of allowed URLs for download`addAllowedType(string $type, bool $binary): void`Add a `Content-Type` to the allowed list, `true` = Base64 encoding, `false` = URL encoding`removeAllowedType(string $type): void`Remove a `Content-Type` from the allowed list`isAllowedType(string $type, string &$errorMessage): bool`Check if a given `Content-Type` is allowed (this method will be used by drivers)`setTemporary(string $path): void`Set the temporary storage path or stream for downloaded content (e.g., `/mnt/storage/`, `php://temp`, `php://memory`).`getTemporary(): resource|null`Get the temporary stream resource used for downloaded content`download(string $url): void`Perform the download`setResponseCacheTime(int $seconds): void`Set the cache duration (in seconds) or disable cache for `Proxy::response()` or `Proxy::jsonp()``response(): void`Dump response to output`jsonp(string $callback): void`Output JSONP callback with URL or data URI content`getContents([int $length[, int $offset]]): string|null`If last download was successful, contents will be returned`getContentType(): string|null`If last download was successful, `Content-Type` will be returned`getHttpStatus(): int|null`If last download was successful, HTTP status will be returned`reset(): void`Reset last downloadGeneric options
---------------

[](#generic-options)

Generic options allow you to customize driver behavior through their native configuration mechanisms (cURL options or stream contexts). Since each driver may require different types of settings, the most flexible approach is to allow these options to store any value. This is particularly useful when developing a new driver. Existing options include:

UsageDescription`setOptions('curl', array $value)`Options for `CurlDriver`. See: `setOptions('stream', array $value)`Options for `StreamDriver`. See: To configure the *cURL* driver, use `'curl'` as the first parameter, for example `$proxy->setOptions('curl', [ ... ]);`, an example to change the SSL version:

```
$proxy->setOptions('curl', [
    CURLOPT_SSLVERSION => CURL_SSLVERSION_TLSv1_3
]);
```

An example to disable SSL verification (for local testing, don't use in a production environment):

```
$proxy->setOptions('curl', [
    CURLOPT_SSL_VERIFYHOST => 0,
    CURLOPT_SSL_VERIFYPEER => false
]);
```

For more constants options to be used with `$proxy->setOptions('curl', [ ... ])`, see:

To configure the Stream driver, use `'stream'` as the first parameter in `setOptions()`, an example to set the HTTP protocol version:

```
$proxy->setOptions('stream', [
    'http' => [
        'protocol_version' => 1.0,
    ]
]);
```

Example SSL configuration:

```
$proxy->setOptions('stream', [
    'ssl' => [
        'verify_peer'   => true,
        'cafile'        => '/foo/bar/baz/cacert.pem',
        'verify_depth'  => 5,
        'CN_match'      => 'secure.example.com'
    ]
]);
```

`Content-Type` allowed
----------------------

[](#content-type-allowed)

When executing the `download()` method, a `Content-Type` validation will be performed, by default the following `Content-Type`s are allowed:

`Content-Type``Proxy::jsonp()``image/apng`base64`image/png`base64`image/avif`base64`image/webp`base64`image/gif`base64`image/jpeg`base64`image/svg+xml`URL-encoded`image/svg-xml`URL-encodedYou can define additional allowed Content-Types, for example:

```
$proxy->addAllowedType('image/x-icon', true);
$proxy->addAllowedType('image/vnd.microsoft.icon', true);
```

The method's second parameter specifies whether `Proxy::jsonp()` should use *URL encoding* or *Base64* encoding in the data URI scheme.

To remove an allowed `Content-Type` use the `Proxy::removeAllowedType()` method, example:

```
$proxy->removeAllowedType('image/apng');
```

How to use
----------

[](#how-to-use)

To return the download response directly to the browser, use the `Proxy::response()` method:

```
use Inphinit\Proxy\Proxy;
use Inphinit\Proxy\Drivers\CurlDriver;
use Inphinit\Proxy\Drivers\StreamDriver;

$proxy = new Proxy();

$proxy->setDrivers([
    CurlDriver::class,
    StreamDriver::class
]);

$proxy->download($url);

$proxy->response();
```

If you want to use the JSONP format, replace the `Proxy::response` method with `Proxy::jsonp()`. In this example, the callback will return and receive the content in *DATA URI* format:

```
use Inphinit\Proxy\Proxy;
use Inphinit\Proxy\Drivers\CurlDriver;
use Inphinit\Proxy\Drivers\StreamDriver;

if (empty($_GET['callback'])) {
    http_response_code(400);
    die('Missing callback');
}

$proxy = new Proxy();

$proxy->setDrivers([
    CurlDriver::class,
    StreamDriver::class
]);

try {
    $proxy->download($url);
    $proxy->jsonp($_GET['callback']);
} catch (Exception $ee) {
}
```

If you need to handle content, you can use the `Proxy::getContents()`, `Proxy::getContentType()`, `Proxy::getHttpStatus()` methods:

```
use Inphinit\Proxy\Proxy;
use Inphinit\Proxy\Drivers\CurlDriver;
use Inphinit\Proxy\Drivers\StreamDriver;

$proxy = new Proxy();

$proxy->setDrivers([
    CurlDriver::class,
    StreamDriver::class
]);

try {
    $proxy->download($url);

    // Success
    $contents = $proxy->getContents();
    $contentType = $proxy->getContentType();
    $httpStatus = $proxy->getHttpStatus();

    ...

} catch (Exception $ee) {
    $code = $ee->getCode();
    $message = $ee->getMessage();

    echo 'Error: (', $code, ') ', $message;
}
```

In the examples so far, CurlDriver takes priority, and uses `StreamDriver` as a fallback, but you can change this, in a hypothetical example, if you only want to use `StreamDriver`:

```
$proxy->setDrivers([
    StreamDriver::class
]);
```

You can also limit the URLs that the proxy can access:

```
$proxy->setAllowedUrls([
    'https://domain1.com/',        // Allows requests on any path to https://domain1.com
    'https://domain2.com/images/', // Allows requests from the path /images/ on https://domain2.com
    'https://*.mainsite.io/',      // Allows requests on subdomains of mainsite.io
    'https://foo.io:8000/',        // Allows requests to foo.io with port 8000
    '*://other.io/',               // Allows HTTPS and HTTP requests to other.io
]);

$proxy->download($url);
```

Writing your own driver
-----------------------

[](#writing-your-own-driver)

The following methods are required to write an `Inphinit\Proxy` compatible driver

MethodDescription`__construct(Proxy $proxy)`It will receive the `Proxy` instance`available(): bool`It will inform if the server has support`exec(string $url, int &$httpStatus, string &$contentType, int &$errorCode, string &$errorMessage): void`It will execute the driver and fill in the references*Optionally* you can use `InterfaceDriver` to avoid errors when writing:

```
use Inphinit\Proxy\Drivers\InterfaceDriver;
use Inphinit\Proxy\Proxy;

class CustomDriver implements InterfaceDriver
{
    public function __construct(Proxy $proxy)
    {
        ...
    }

    public function available()
    {
        ...
    }

    public function exec($url, &$httpStatus, &$contentType, &$errorCode, &$errorMessage)
    {
        ...
    }
}
```

Once created you can use it like this:

```
$proxy->setDrivers([
    CustomDriver::class
]);
```

Common issues and solutions
---------------------------

[](#common-issues-and-solutions)

When you add an image from another domain to a `` element and then try to export it as a new image, a security error occurs (what actually happens is a security lock), which can return the error:

> SecurityError: DOM Exception 18
>
> Error: An attempt was made to break through the security policy of the user agent.

If you're using Google Maps (or Google Maps Static), you might see this error in the console:

> Google Maps API error: MissingKeyMapError

You need to obtain an API Key:

If you get this error:

> Access to Image at 'file:///...' from origin 'null' has been blocked by CORS policy: Invalid response. Origin 'null' is therefore not allowed access.

This means you are not using an HTTP server, html2canvas does not work with the `file:///` protocol; to resolve this, use Apache, Nginx, or IIS with PHP.

Debugging with Web Console from DevTools
----------------------------------------

[](#debugging-with-web-console-from-devtools)

If you encounter any issues, check your browser's Web Console (Network and Console tabs) to inspect proxy requests and responses, see documentations:

- Firefox:
- Chrome:
- Microsoft Edge:

You can also test the proxy directly by visiting:

`http://[DOMAIN]/[PATH]/proxy?url=http%3A%2F%2Fmaps.googleapis.com%2Fmaps%2Fapi%2Fstaticmap%3Fcenter%3D40.714728%2C-73.998672%26zoom%3D12%26size%3D800x600%26maptype%3Droadmap%26sensor%3Dfalse%261&callback=html2canvas_0`

Replace `[DOMAIN]` with your domain (e.g., `127.0.0.1`) and replace `[PATH]` by your project folder (e.g., `project-1/test`), something like:

`http://localhost/project-1/test/proxy?url=http%3A%2F%2Fmaps.googleapis.com%2Fmaps%2Fapi%2Fstaticmap%3Fcenter%3D40.714728%2C-73.998672%26zoom%3D12%26size%3D800x600%26maptype%3Droadmap%26sensor%3Dfalse%261&callback=html2canvas_0`

###  Health Score

40

—

FairBetter than 88% of packages

Maintenance89

Actively maintained with recent releases

Popularity23

Limited adoption so far

Community23

Small or concentrated contributor base

Maturity23

Early-stage or recently created project

 Bus Factor1

Top contributor holds 97.5% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~45 days

Recently: every ~78 days

Total

8

Last Release

57d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/59fe203ccf639d985a00f1ed5fabeb042e2a74829708d23d0fe02e95d6599821?d=identicon)[brcontainer](/maintainers/brcontainer)

---

Top Contributors

[![brcontainer](https://avatars.githubusercontent.com/u/4368952?v=4)](https://github.com/brcontainer "brcontainer (158 commits)")[![bryant1410](https://avatars.githubusercontent.com/u/3905501?v=4)](https://github.com/bryant1410 "bryant1410 (1 commits)")[![jasonhewes123](https://avatars.githubusercontent.com/u/172520696?v=4)](https://github.com/jasonhewes123 "jasonhewes123 (1 commits)")[![marcalj](https://avatars.githubusercontent.com/u/63667?v=4)](https://github.com/marcalj "marcalj (1 commits)")[![n0f](https://avatars.githubusercontent.com/u/10847587?v=4)](https://github.com/n0f "n0f (1 commits)")

---

Tags

html2canvashtml2canvas-proxyphpproxy-serverproxycorshtml2canvas

### Embed Badge

![Health badge](/badges/inphinit-proxy/health.svg)

```
[![Health](https://phpackages.com/badges/inphinit-proxy/health.svg)](https://phpackages.com/packages/inphinit-proxy)
```

###  Alternatives

[asm89/stack-cors

Cross-origin resource sharing library and stack middleware

1.3k180.6M24](/packages/asm89-stack-cors)[fruitcake/php-cors

Cross-origin resource sharing library for the Symfony HttpFoundation

314242.1M35](/packages/fruitcake-php-cors)[nette/http

🌐 Nette Http: abstraction for HTTP request, response and session. Provides careful data sanitization and utility for URL and cookies manipulation.

48819.2M541](/packages/nette-http)[jenssegers/proxy

Proxy library that forwards requests to the desired url and returns the response.

940487.2k4](/packages/jenssegers-proxy)[tuupola/cors-middleware

PSR-7 and PSR-15 CORS middleware

1331.8M24](/packages/tuupola-cors-middleware)[neomerx/cors-psr7

Framework agnostic (PSR-7) CORS implementation (www.w3.org/TR/cors/)

682.4M19](/packages/neomerx-cors-psr7)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
