PHPackages                             he4rt/reqxide - 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. he4rt/reqxide

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

he4rt/reqxide
=============

PHP TLS/HTTP fingerprinting library for browser emulation

0.2.0(1mo ago)3532↓90.9%MITPHPPHP ^8.4.0CI passing

Since Mar 28Pushed 1mo agoCompare

[ Source](https://github.com/he4rt/reqxide)[ Packagist](https://packagist.org/packages/he4rt/reqxide)[ GitHub Sponsors](https://github.com/danielhe4rt)[ RSS](/packages/he4rt-reqxide/feed)WikiDiscussions 0.x Synced 3w ago

READMEChangelog (6)Dependencies (21)Versions (19)Used By (0)

Reqxide
=======

[](#reqxide)

PHP TLS/HTTP fingerprinting library for browser emulation.

[![Tests](https://github.com/he4rt/reqxide/actions/workflows/tests.yml/badge.svg)](https://github.com/he4rt/reqxide/actions)[![Latest Version](https://camo.githubusercontent.com/9baf34089da2c07016c07f7839e01f0383c36539b9e37b6b9416d61b71aa546c/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f68653472742f72657178696465)](https://packagist.org/packages/he4rt/reqxide)[![License](https://camo.githubusercontent.com/282d3926f897c32dc8871d9bae22f1a2bc7888d3464a9323ecfd9a6dc8eb69e4/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f68653472742f72657178696465)](https://packagist.org/packages/he4rt/reqxide)

---

> **Warning:** This package is under active development and not yet stable. The API may change between minor versions. Use in production at your own risk.

Reqxide brings TLS and HTTP/2 fingerprinting to PHP. It emulates real browser fingerprints (Chrome, Firefox, Safari, Edge, OkHttp) so your HTTP requests look identical to traffic from actual browsers. Built on top of `curl_impersonate`, it provides a PSR-18 compatible client with transparent browser emulation.

Ported from Rust's [wreq](https://github.com/nickel-org/wreq).

> **Requires [PHP 8.4+](https://php.net/releases/)**

Why?
----

[](#why)

Anti-bot systems like Cloudflare, Akamai, and DataDome fingerprint TLS handshakes and HTTP/2 frames to distinguish bots from real browsers. Standard PHP HTTP clients (Guzzle, Symfony HttpClient) produce machine-like fingerprints that get blocked immediately.

Reqxide solves this by controlling:

- **TLS ClientHello** — cipher suites, elliptic curves, signature algorithms, extensions, ALPN, GREASE, ECH
- **HTTP/2 SETTINGS** — frame order, window sizes, pseudo-header order, stream priorities
- **Header order and casing** — browsers send headers in specific order with specific casing

The result: your requests produce the same JA3/JA4 fingerprints as real browsers.

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

[](#installation)

```
composer require he4rt/reqxide
```

Quick Start
-----------

[](#quick-start)

```
use Reqxide\Client;
use Reqxide\Emulation\Browser;

$client = Client::builder()
    ->emulation(Browser::Chrome131)
    ->build();

$response = $client->get('https://example.com')->send();

echo $response->getStatusCode(); // 200
echo (string) $response->getBody();
```

Usage
-----

[](#usage)

### Browser Emulation

[](#browser-emulation)

Pick a browser profile. Each profile bundles the exact TLS configuration, HTTP/2 settings, default headers, and header ordering that the real browser uses.

```
use Reqxide\Client;
use Reqxide\Emulation\Browser;

// Chrome (latest)
$client = Client::builder()->emulation(Browser::Chrome131)->build();

// Firefox
$client = Client::builder()->emulation(Browser::Firefox136)->build();

// Safari (macOS, iOS, iPad)
$client = Client::builder()->emulation(Browser::Safari18)->build();
$client = Client::builder()->emulation(Browser::SafariIOS18)->build();

// Edge (Chromium-based, different sec-ch-ua)
$client = Client::builder()->emulation(Browser::Edge131)->build();

// OkHttp (Android HTTP client)
$client = Client::builder()->emulation(Browser::OkHttp5)->build();
```

### Making Requests

[](#making-requests)

Reqxide implements PSR-18 (`ClientInterface`) and provides convenience methods:

```
// Convenience API
$response = $client->get('https://api.example.com/users')->send();
$response = $client->post('https://api.example.com/users')
    ->json(['name' => 'Daniel', 'email' => 'daniel@he4rt.com'])
    ->send();

// With headers and auth
$response = $client->get('https://api.example.com/me')
    ->bearerToken('your-token')
    ->header('X-Custom', 'value')
    ->send();

// Form data
$response = $client->post('https://example.com/login')
    ->form(['username' => 'admin', 'password' => 'secret'])
    ->send();

// Query parameters
$response = $client->get('https://api.example.com/search')
    ->query(['q' => 'reqxide', 'page' => '1'])
    ->send();

// PSR-18 standard (drop-in for any PSR-18 consumer)
$response = $client->sendRequest($psrRequest);
```

### Proxy Support

[](#proxy-support)

HTTP, HTTPS, SOCKS4, and SOCKS5 with optional authentication:

```
use Reqxide\Proxy\Proxy;

$client = Client::builder()
    ->emulation(Browser::Chrome131)
    ->proxy(Proxy::http('45.38.89.88:6023'))
    ->build();

// SOCKS5
$client = Client::builder()
    ->emulation(Browser::Chrome131)
    ->proxy(Proxy::socks5('127.0.0.1:1080'))
    ->build();

// With authentication
$proxy = new Proxy(
    scheme: ProxyScheme::Http,
    host: 'proxy.example.com',
    port: 8080,
    username: 'user',
    password: 'pass',
);
```

### Cookie Persistence

[](#cookie-persistence)

```
use Reqxide\Cookie\CookieJar;

// Automatic cookie jar
$client = Client::builder()
    ->emulation(Browser::Chrome131)
    ->cookieStore(true)
    ->build();

// Shared cookie jar across clients
$jar = new CookieJar();

$client = Client::builder()
    ->emulation(Browser::Chrome131)
    ->cookieStore($jar)
    ->build();

// Cookies persist across requests automatically
$client->get('https://example.com/login')->form([...])->send();
$client->get('https://example.com/dashboard')->send(); // sends session cookie
```

### Redirect &amp; Retry

[](#redirect--retry)

```
use Reqxide\Redirect\RedirectPolicy;
use Reqxide\Retry\RetryPolicy;

$client = Client::builder()
    ->emulation(Browser::Chrome131)
    ->redirect(RedirectPolicy::limited(10))  // follow up to 10 redirects
    ->retry(RetryPolicy::default())          // retry 5xx, max 2 attempts, 20% budget
    ->build();

// Disable redirects
$client = Client::builder()
    ->emulation(Browser::Chrome131)
    ->redirect(RedirectPolicy::none())
    ->build();

// Custom retry logic
$client = Client::builder()
    ->emulation(Browser::Chrome131)
    ->retry(RetryPolicy::custom(
        classifier: fn($req, $res, $err) => $res?->getStatusCode() === 429,
        maxRetries: 5,
        baseDelayMs: 1000,
    ))
    ->build();
```

### Client Configuration

[](#client-configuration)

```
$client = Client::builder()
    ->emulation(Browser::Chrome131)
    ->proxy(Proxy::socks5('127.0.0.1:1080'))
    ->timeout(30)                              // seconds
    ->connectTimeout(10)                       // seconds
    ->cookieStore(true)                        // enable cookie jar
    ->redirect(RedirectPolicy::limited(10))    // follow redirects
    ->retry(RetryPolicy::default())            // retry on failure
    ->verify(false)                            // disable SSL verification
    ->defaultHeaders(['X-App' => 'myapp'])     // extra headers on every request
    ->build();
```

Architecture
------------

[](#architecture)

```
User Code
    |
    v
+---------------------------------+
|  PSR-18 Client (Reqxide\Client) |
|  sendRequest(RequestInterface)  |
+---------------------------------+
    |
    v
+---------------------------------+
|     Middleware Pipeline          |
|  Cookie -> Redirect -> Retry -> |
|  Compression -> Transport       |
+---------------------------------+
    |
    +--------+---------+
    v        v         v
  FFI     ext/curl   Process
  (full)  (partial)  (binary)
    |        |         |
    v        v         v
  libcurl-impersonate

```

**Three transport backends:**

TransportFingerprint ControlRequires`FfiTransport`Full (TLS + HTTP/2 + headers)PHP FFI + libcurl-impersonate`CurlTransport`Partial (TLS ciphers, curves, ALPN)ext-curl`ProcessTransport`Full (via binary)curl-impersonate binary`TransportFactory::create()` auto-detects the best available transport.

Framework Integration
---------------------

[](#framework-integration)

### Guzzle

[](#guzzle)

```
use Reqxide\Adapter\Guzzle\GuzzleHandlerAdapter;
use Reqxide\Emulation\Browser;

$handler = new GuzzleHandlerAdapter(Browser::Chrome131);
$guzzle = new \GuzzleHttp\Client([
    'handler' => \GuzzleHttp\HandlerStack::create($handler),
]);

$response = $guzzle->get('https://example.com');
```

### Laravel

[](#laravel)

```
// In a ServiceProvider
use Reqxide\Client;
use Reqxide\Emulation\Browser;

$this->app->singleton(Client::class, fn () =>
    Client::builder()->emulation(Browser::Chrome131)->build()
);

// Usage
$client = app(Client::class);
$response = $client->get('https://api.example.com/data')->send();
```

### Symfony

[](#symfony)

```
use Reqxide\Adapter\Symfony\SymfonyClientAdapter;
use Reqxide\Emulation\Browser;

$client = new SymfonyClientAdapter(Browser::Chrome131);
$response = $client->request('GET', 'https://example.com', [
    'headers' => ['Accept' => 'application/json'],
]);
```

Supported Browsers
------------------

[](#supported-browsers)

BrowserVersionsKey DifferencesChrome128, 129, 130, 131130+ has X25519MLKEM768 (post-quantum), GREASE enabledFirefox135, 136No GREASE, FFDHE curves, Sec-Fetch-\* headers, different pseudo-header orderSafari18 (macOS, iPad, iOS)No GREASE, no ECH, minimal headers, different HTTP/2 window sizesEdge131Chromium base + Edge-specific User-Agent and sec-ch-uaOkHttp4, 5HTTP/1.1 only, no browser headers, Android client fingerprint### Fingerprint Accuracy

[](#fingerprint-accuracy)

Each profile controls the full TLS/HTTP/2 fingerprint:

```
Chrome 131:
  JA3:  9e2da15d3e1b6931c6fbaa3f9ac9cd89
  JA4:  t13d913h2_f91f431d341e_882d495ac381
  HTTP: h2  |  Ciphers: 9

Firefox 136:
  JA3:  bdc242f0548bc1fcc45d12edc713b8e1
  JA4:  t13d1513h2_8daaf6152771_882d495ac381
  HTTP: h2  |  Ciphers: 15

```

How It Works
------------

[](#how-it-works)

When you select `Browser::Chrome131`, reqxide configures:

**TLS layer:**

- Cipher suites in Chrome's exact order (9 ciphers)
- Elliptic curves: X25519MLKEM768, X25519, P-256, P-384
- Signature algorithms: 8 algorithms in Chrome's order
- Key shares: X25519MLKEM768 + X25519
- Extensions: GREASE, ECH GREASE, permuted extensions, OCSP stapling, SCT

**HTTP/2 layer:**

- SETTINGS frame: header table 65536, push disabled, max streams 1000, window 6MB, max frame 16384, max header list 262144
- Pseudo-header order: `:method`, `:authority`, `:scheme`, `:path`
- Connection window: 15663105 bytes

**Headers:**

- Default browser headers (sec-ch-ua, User-Agent, Accept, Accept-Encoding, Accept-Language)
- Header ordering matching Chrome's exact send order
- Case preservation (sec-ch-ua, not Sec-Ch-Ua)

Testing
-------

[](#testing)

```
# Full quality suite (lint + phpstan + pest + rector)
composer test

# Individual checks
composer test:lint           # Laravel Pint formatting
composer test:types          # PHPStan level max
composer test:unit           # Pest with 100% coverage
composer test:type-coverage  # 100% type coverage
composer test:refactor       # Rector dry-run

# Run a specific test
./vendor/bin/pest tests/Unit/Tls/TlsOptionsTest.php
./vendor/bin/pest --filter="Chrome 131"

# Integration tests (requires network)
./vendor/bin/pest --group=integration
```

Project Structure
-----------------

[](#project-structure)

```
src/
  Client.php                    # PSR-18 ClientInterface
  ClientBuilder.php             # Fluent builder
  RequestBuilder.php            # Per-request builder (get, post, json, form...)
  Contract/                     # Interfaces (Transport, CookieStore, Profile, Redirect, Retry)
  Emulation/                    # Browser enum, Profile, Catalog (Chrome, Firefox, Safari, Edge, OkHttp)
  Tls/                          # TLS options, enums (ciphers, curves, sigalgs, versions)
  Http2/                        # HTTP/2 options (settings, pseudo-headers, priorities)
  Http1/                        # HTTP/1 options (header ordering)
  Transport/                    # CurlTransport, FfiTransport, ProcessTransport, TransportFactory
  Middleware/                   # Pipeline, Cookie, Redirect, Retry, Compression
  Cookie/                       # CookieJar (RFC 6265), Cookie value object
  Proxy/                        # Proxy value object, ProxyScheme enum
  Redirect/                     # RedirectPolicy (limited, none, custom)
  Retry/                        # RetryPolicy, RetryBudget (token bucket)
  Adapter/                      # Guzzle, Laravel, Symfony integrations
  Exception/                    # PSR-18 compliant exception hierarchy

```

Credits
-------

[](#credits)

- Ported from [wreq](https://github.com/nickel-org/wreq) (Rust)
- Powered by [curl-impersonate](https://github.com/lwthiker/curl-impersonate)
- Built by [He4rt Developers](https://github.com/he4rt)

License
-------

[](#license)

Reqxide is open-sourced software licensed under the **[MIT license](https://opensource.org/licenses/MIT)**.

###  Health Score

44

—

FairBetter than 91% of packages

Maintenance91

Actively maintained with recent releases

Popularity18

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity50

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 ~8 days

Total

7

Last Release

44d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/02c87326bfe0283475a9bd73a12100d564617668fd9fd57eb703ea08f420898e?d=identicon)[DanielHe4rt](/maintainers/DanielHe4rt)

---

Top Contributors

[![danielhe4rt](https://avatars.githubusercontent.com/u/6912596?v=4)](https://github.com/danielhe4rt "danielhe4rt (78 commits)")

---

Tags

phphttp2tlsFingerprintcurl-impersonatebrowser-emulation

###  Code Quality

TestsPest

Static AnalysisPHPStan, Rector

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/he4rt-reqxide/health.svg)

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

###  Alternatives

[guzzlehttp/psr7

PSR-7 message implementation that also provides common utility methods

7.9k1.1B3.8k](/packages/guzzlehttp-psr7)[tempest/framework

The PHP framework that gets out of your way.

2.2k31.1k12](/packages/tempest-framework)[cakephp/cakephp

The CakePHP framework

8.8k19.1M1.7k](/packages/cakephp-cakephp)[mollie/mollie-api-php

Mollie API client library for PHP. Mollie is a European Payment Service provider and offers international payment methods such as Mastercard, VISA, American Express and PayPal, and local payment methods such as iDEAL, Bancontact, SOFORT Banking, SEPA direct debit, Belfius Direct Net, KBC Payment Button and various gift cards such as Podiumcadeaukaart and fashioncheque.

60315.4M74](/packages/mollie-mollie-api-php)[telnyx/telnyx-php

Official Telnyx PHP SDK — APIs for Voice, SMS, MMS, WhatsApp, Fax, SIP Trunking, Wireless IoT, Call Control, and more. Build global communications on Telnyx's private carrier-grade network.

35729.6k2](/packages/telnyx-telnyx-php)[flow-php/flow

PHP ETL - Extract Transform Load - Data processing framework

84735.1k](/packages/flow-php-flow)

PHPackages © 2026

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