PHPackages                             truongbo/proxy-rotation - 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. truongbo/proxy-rotation

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

truongbo/proxy-rotation
=======================

Proxy Rotation with Load balancing strategies

v2.2.2(3y ago)847MITPHPPHP ^8.1

Since Nov 5Pushed 3y ago1 watchersCompare

[ Source](https://github.com/truongbo17/proxy-rotator)[ Packagist](https://packagist.org/packages/truongbo/proxy-rotation)[ RSS](/packages/truongbo-proxy-rotation/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (2)Dependencies (2)Versions (3)Used By (0)

Proxy Rotation with Laravel Guzzle
==================================

[](#proxy-rotation-with-laravel-guzzle)

 [![Proxy Rotation Logo](./img.png)](./img.png)

### Description

[](#description)

- Implement Nginx simple load balancing strategies to build a Package Proxy Rotation to use with Guzzle or anymore...
- Use only effective, consistent and simple strategies to rotate proxies

---

### Optional Features

[](#optional-features)

- [Installation](#installation)
- [Quick Use](#quick-use)
- [Sort Nodes](#sort-nodes)
- [Max Use](#max-use)

### Strategy

[](#strategy)

- [Random](#random)
- [Frequency](#frequency)
- [Round Robin](#round-robin)
- [Weighted Round Robin](#weighted-round-robin)
- [Multiple Dynamic](#multiple-dynamic)

### Multiple Endpoint

[](#multiple-endpoint)

Automatically retry connect and switch between endpoint

- [Introduction](MultipleEndpoint.md)

Next feature
------------

[](#next-feature)

- Use backup hosts (if the main host is not accessible, Guzzle will automatically connect to the backup hosts to get data...) ✔️
- Configure strategies to run separately with hosts, smarter ✔️
- Automatically retry connecting hosts when it fails to connect (configure number of retries, response code types) ✔️
- Load balancing, apply separate strategies to each Cluster ❌
- Anymore...

---

Installation
------------

[](#installation)

Install the package:

```
composer require truongbo/proxy-rotation
```

Run test:

```
./vendor/bin/phpunit
```

Publish package files (config):

```
php artisan vendor:publish --provider="TruongBo\ProxyRotation\ProxyRotationServiceProvider"
```

---

Quick Use
---------

[](#quick-use)

You need to choose a rotation strategy and configure it with Rotation:

```
use TruongBo\ProxyRotation\Rotation;
use TruongBo\ProxyRotation\Strategy\RoundRobin;

$rotation = new Rotation(new RoundRobin(counter: 0));
```

Initialize a cluster consisting of proxy nodes:

```
use TruongBo\ProxyRotation\ProxyServer\ProxyCluster;
use TruongBo\ProxyRotation\ProxyServer\ProxyNode;

$proxy_cluster = new ProxyCluster(
        cluster_name: 'cluster1',
        array_proxy_node: [
            new ProxyNode(name: 'proxy-node1'),
            new ProxyNode(name: 'proxy-node2'),
            new ProxyNode(name: 'proxy-node3'),
            new ProxyNode(name: 'proxy-node4'),
        ]);
```

Then, we should connect ProxyMiddleware to Guzzle for the proxy balancing to work:

```
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Client;
use TruongBo\ProxyRotation\Middleware\ProxyMiddleware;

$stack = HandlerStack::create();
$stack->push(new ProxyMiddleware(rotation: $rotation,proxy_cluster: $proxy_cluster));

$client = new Client([
    'handler' => $stack,
]);
```

Finished, check it out now:

```
while (true) {
    /** @var ResponseInterface $response */
    $response = $client->get('https://httpbin.org/ip');

    // ...
}
```

Result: (With proxy-node as your proxy address)

```
+-------------+
| proxy-node1 |
| proxy-node2 |
| proxy-node3 |
| proxy-node4 |
| proxy-node1 |
| proxy-node2 |
| proxy-node3 |
| proxy-node4 |
| etc...      |
+-------------+

```

---

Sort Nodes
----------

[](#sort-nodes)

Sort to adjust the order of nodes in ascending or descending order:

```
use TruongBo\ProxyRotation\ProxyServer\ProxyCluster;
use TruongBo\ProxyRotation\ProxyServer\ProxyNode;

$proxy_cluster = new ProxyCluster(
        cluster_name: 'cluster1',
        array_proxy_node: [
            new ProxyNode(name: 'proxy-node1',weight: 1000),
            new ProxyNode(name: 'proxy-node2',weight: 20),
            new ProxyNode(name: 'proxy-node3',weight: 200),
            new ProxyNode(name: 'proxy-node4',weight: 10),
        ]);

$proxy_cluster->sort("desc");
```

Top proxy nodes will be used more and vice versa, for example:

```
+-------------+-------------+
| name        | weight      |
+-------------+-------------+
| proxy-node1 | 1000        |
| proxy-node3 | 200         |
| proxy-node2 | 20          |
| proxy-node4 | 10          |
+-------------+-------------+

```

Sorting nodes can help you use the [Frequency](#frequency) strategy better. Use asc for reverse sort.

---

Max Use
-------

[](#max-use)

- Store the proxy usage count in the cache and count it. If it is used more than allowed, the proxy will be temporarily idle for the configured time period.
- Use only with Random , Frequency and RoundRobin strategies

Example:

```
$cluster = new ProxyCluster('cluster1', [
            new ProxyNode(name: 'node1',weight: 3,max_use: 4,max_use_wait: 10),
            new ProxyNode(name: 'node2',weight: 1,max_use: 2,max_use_wait: 20),
        ]);
```

Everything else runs automatically

---

Random
======

[](#random)

- $input\_random : How are proxies random?

```
- both : All proxy nodes are random
- has_weight : Only the weighted proxy node will be random
- no_weight : Only proxy nodes without weights can be random
```

Config:

```
use TruongBo\ProxyRotation\Rotation;
use TruongBo\ProxyRotation\Strategy\Random;
use TruongBo\ProxyRotation\ProxyServer\ProxyCluster;
use TruongBo\ProxyRotation\ProxyServer\ProxyNode;

$rotation = new Rotation(new Random(input_random: "both"));

$proxy_cluster = new ProxyCluster(
        cluster_name: 'cluster1',
        array_proxy_node: [
            new ProxyNode(name: 'proxy-node1',weight: 20),
            new ProxyNode(name: 'proxy-node2'),
            new ProxyNode(name: 'proxy-node3'),
            new ProxyNode(name: 'proxy-node4',weight: 100),
        ]);
```

Output(both):

```
+-------------+-------------+
| name        | weight      |
+-------------+-------------+
| proxy-node3 | 0           |
| proxy-node1 | 20          |
| proxy-node2 | 0           |
| proxy-node4 | 100         |
+-------------+-------------+

```

---

Frequency
---------

[](#frequency)

More efficient using sort node

```
use TruongBo\ProxyRotation\ProxyServer\ProxyCluster;
use TruongBo\ProxyRotation\ProxyServer\ProxyNode;
use TruongBo\ProxyRotation\Strategy\Frequency;

$rotation = new Rotation(new Frequency(frequency: 0.8, depth: 0.2));

$proxy_cluster = new ProxyCluster(
        cluster_name: 'cluster1',
        array_proxy_node: [
            new ProxyNode(name: 'proxy-node1',weight: 2048),
            new ProxyNode(name: 'proxy-node2',weight: 1024),
            new ProxyNode(name: 'proxy-node3',weight: 512),
            new ProxyNode(name: 'proxy-node4',weight: 256),
            new ProxyNode(name: 'proxy-node5',weight: 256),
            new ProxyNode(name: 'proxy-node6',weight: 64),
            new ProxyNode(name: 'proxy-node7',weight: 32),
            new ProxyNode(name: 'proxy-node8',weight: 16),
            new ProxyNode(name: 'proxy-node9',weight: 8),
            new ProxyNode(name: 'proxy-node10',weight: 4),
        ]);

$cluster->sort("desc");
```

The probability of choosing nodes for Frequency can be visualized as follows::

```
+--------------+--------+
| nodes        | chance |
+--------------+--------+
| proxy-node1  | 40%    |
| proxy-node2  | 40%    |
+--------------+--------+
| proxy-node3  | 2.5%   |
| proxy-node8  | 2.5%   |
| proxy-node5  | 2.5%   |
| proxy-node6  | 2.5%   |
| proxy-node4  | 2.5%   |
| proxy-node7  | 2.5%   |
| proxy-node9  | 2.5%   |
| proxy-node10 | 2.5%   |
+-----------+-----------+

```

---

Round Robin
-----------

[](#round-robin)

The proxies will be rotated in turn ($counter : start counting from somewhere)

```
use TruongBo\ProxyRotation\Rotation;
use TruongBo\ProxyRotation\Strategy\RoundRobin;
use TruongBo\ProxyRotation\ProxyServer\ProxyCluster;
use TruongBo\ProxyRotation\ProxyServer\ProxyNode;

$rotation = new Rotation(new RoundRobin(counter: 0));

$proxy_cluster = new ProxyCluster(
        cluster_name: 'cluster1',
        array_proxy_node: [
            new ProxyNode(name: 'proxy-node1'),
            new ProxyNode(name: 'proxy-node2'),
            new ProxyNode(name: 'proxy-node3'),
            new ProxyNode(name: 'proxy-node4'),
        ]);
```

Output:

```
+-------------+
| proxy-node1 |
| proxy-node2 |
| proxy-node3 |
| proxy-node4 |
| proxy-node1 |
| proxy-node2 |
| proxy-node3 |
| proxy-node4 |
| etc...      |
+-------------+

```

- You can interfere with proxy usage for a certain period of time if the proxy is restricted from use.Using [Max Use](#max-use)

---

Weighted Round Robin
--------------------

[](#weighted-round-robin)

The number of times this proxy node is called is the weight parameter passed in the initialization of the ProxyNode ($counter : start counting from somewhere)

```
use TruongBo\ProxyRotation\Rotation;
use TruongBo\ProxyRotation\Strategy\WeightedRoundRobin;
use TruongBo\ProxyRotation\ProxyServer\ProxyCluster;
use TruongBo\ProxyRotation\ProxyServer\ProxyNode;

$rotation = new Rotation(new WeightedRoundRobin(counter: 0));

$proxy_cluster = new ProxyCluster(
        cluster_name: 'cluster1',
        array_proxy_node: [
            new ProxyNode(name: 'proxy-node1', weight: 3),
            new ProxyNode(name: 'proxy-node2'),
            new ProxyNode(name: 'proxy-node3', weight: 1),
            new ProxyNode(name: 'proxy-node4', weight: 1),
        ]);
```

Output:

```
+-------------+
| proxy-node1 |
| proxy-node1 |
| proxy-node1 |
| proxy-node3 |
| proxy-node4 |
| etc...      |
+-------------+

```

- Proxy Node without weight will not be used

---

Multiple Dynamic
----------------

[](#multiple-dynamic)

Dynamically change strategies according to the passed callable condition (Absolutely do not use if you do not know about it)

```
use TruongBo\ProxyRotation\Rotation;
use TruongBo\ProxyRotation\Strategy\WeightedRoundRobin;
use TruongBo\ProxyRotation\ProxyServer\ProxyCluster;
use TruongBo\ProxyRotation\ProxyServer\ProxyNode;

$rotation = new Rotation(new MultipleDynamic(
            new RoundRobin(counter: 0),
            new Random(input_random: "has_weight"),
            new WeightedRoundRobin(counter: 0),
        ));

$proxy_cluster = new ProxyCluster(
        cluster_name: 'cluster1',
        array_proxy_node: [
            new ProxyNode(name: 'proxy-node1', weight: 3),
            new ProxyNode(name: 'proxy-node2'),
            new ProxyNode(name: 'proxy-node3', weight: 1),
            new ProxyNode(name: 'proxy-node4', weight: 1),
        ]);

        while (true) {
            $node = $rotation->pick($cluster, function (ProxyNode $proxy_node){
                //condition switch between strategies in here.
            });

            echo $node?->name;
        }
```

---

###  Health Score

27

—

LowBetter than 49% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity13

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity56

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% 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 ~60 days

Total

2

Last Release

1224d ago

Major Versions

v1.0.3 → v2.2.22023-01-05

### Community

Maintainers

![](https://www.gravatar.com/avatar/f5b50808bae941c66b2572f44a4ae4c77554ea11fd98f2417bdc43f59eda9aff?d=identicon)[truongbo17](/maintainers/truongbo17)

---

Top Contributors

[![truongbo17](https://avatars.githubusercontent.com/u/91400591?v=4)](https://github.com/truongbo17 "truongbo17 (26 commits)")

---

Tags

crawlguzzleload-balancingproxyproxy-rotationproxy-rotatorround-robinstrategyrandomroundloadbalancingweightedrobin

### Embed Badge

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

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

###  Alternatives

[spatie/crawler

Crawl all internal links found on a website

2.8k16.3M52](/packages/spatie-crawler)[orangesoft/throttler

Load balancer between nodes.

1732.3k1](/packages/orangesoft-throttler)[omniphx/forrest

A Laravel library for Salesforce

2724.4M8](/packages/omniphx-forrest)[akamai-open/edgegrid-client

Implements the Akamai {OPEN} EdgeGrid Authentication specified by https://developer.akamai.com/introduction/Client\_Auth.html

482.5M6](/packages/akamai-open-edgegrid-client)[muhammadhuzaifa/telescope-guzzle-watcher

Telescope Guzzle Watcher provide a custom watcher for intercepting http requests made via guzzlehttp/guzzle php library. The package uses the on\_stats request option for extracting the request/response data. The watcher intercept and log the request into the Laravel Telescope HTTP Client Watcher.

98239.8k1](/packages/muhammadhuzaifa-telescope-guzzle-watcher)[ory/hydra-client-php

Documentation for all of Ory Hydra's APIs.

1710.8k](/packages/ory-hydra-client-php)

PHPackages © 2026

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