pdphilip/cf-request

Cloudflare Laravel Request

Fund package maintenance!
pdphilip

Installs: 24 020

Dependents: 1

Suggesters: 0

Security: 0

Stars: 27

Watchers: 1

Forks: 0

Open Issues: 0

pkg:composer/pdphilip/cf-request

v3.0.0 2026-02-20 20:45 UTC

README

Cloudflare Laravel Request

Cloudflare Laravel Request

Latest Version on Packagist GitHub Tests Action Status Total Downloads

A drop-in replacement for Laravel's Request that extracts Cloudflare metadata - geolocation, device info, bot detection - from transform rule headers. Use it as a facade or inject it like a normal request.

public function register(CfRequest $request)
{
    if ($request->isBot()) {
        abort(403);
    }

    $country  = $request->country();   // 'US'
    $timezone = $request->timezone();  // 'America/New_York'
    $device   = $request->deviceType(); // 'mobile'
    $browser  = $request->browserName(); // 'Chrome'
}

Requirements

  • PHP 8.2+
  • Laravel 10, 11, or 12
  • Cloudflare as a proxy (works without it, CF-specific methods return null)

Installation

composer require pdphilip/cf-request
php artisan cf-request:install

Cloudflare Setup

The package reads custom headers that Cloudflare injects via transform rules. You need to configure these rules on your Cloudflare zone.

Option 1: Via Cloudflare API (recommended)

Step 1: Get your Zone ID

  • Cloudflare dashboard > select your domain
  • Copy the Zone ID from the sidebar
  • Save as CF_API_ZONE_ID in your .env
Zone ID location

Step 2: Create an API Token

Token permissions
  • Save the token as CF_API_TOKEN in your .env

Step 3: Run the command

php artisan cf-request:headers

This creates a "Laravel Headers" transform rule on your zone with all required headers.

Step 4: Verify

php artisan cf-request:status

Shows a grouped table of every expected header and whether it's configured on Cloudflare.

Option 2: Manual setup on Cloudflare dashboard

Navigate to Transform Rules

  • Cloudflare dashboard > select your domain
  • Rules > Transform Rules > Modify Request Header
  • Create a Rule

Rule configuration

  • Name: Laravel Headers
  • When: All incoming requests
  • Then: Set the following headers:
Type Header Expression
Set dynamic X-IP ip.src
Set dynamic X-ASN ip.src.asnum
Set dynamic X-AGENT http.user_agent
Set dynamic X-COUNTRY ip.src.country
Set dynamic X-CITY ip.src.city
Set dynamic X-REGION ip.src.region
Set dynamic X-CONTINENT ip.src.continent
Set dynamic X-POSTAL-CODE ip.src.postal_code
Set dynamic X-LAT ip.src.lat
Set dynamic X-LON ip.src.lon
Set dynamic X-TIMEZONE ip.src.timezone.name
Set dynamic X-REFERER http.referer
Set dynamic X-LANG http.request.accepted_languages[0]
Set dynamic X-BOT-CAT cf.verified_bot_category

Usage

Use the CfRequest facade or inject CfRequest $request in place of Laravel's Request.

Geolocation

$request->country();    // 'AU' (ISO 3166-1 Alpha-2, validated)
$request->city();       // 'Sydney'
$request->region();     // 'New South Wales'
$request->continent();  // 'OC'
$request->postalCode(); // '2000'
$request->lat();        // '-33.8688'
$request->lon();        // '151.2093'
$request->geo();        // ['lat' => '-33.8688', 'lon' => '151.2093'] or null
$request->timezone();   // 'Australia/Sydney'
$request->isTor();      // true if traffic is from the Tor network

Country codes are validated against the ISO 3166-1 standard. Non-country values like T1 (Tor) and XX (unknown) return null from country(), which also nulls all dependent geo fields. Use isTor() to detect Tor traffic specifically.

Bot Detection

$request->isBot();      // true/false (CrawlerDetect + DeviceDetector)
$request->bot();        // 'Googlebot' or 'no_user_agent' or false

// CF verified bot category (all plans)
$request->verifiedBotCategory(); // 'search_engine', 'advertising', etc.
$request->isVerifiedBot();       // true/false

// CF bot score (Enterprise only)
$request->botScore();     // 0-99 integer or null
$request->botScoreData(); // ['score' => 99, 'is_bot' => false, 'key' => 'human', 'value' => '...']

Bot detection works without Cloudflare. The package uses CrawlerDetect (1,400+ bot patterns) as the primary check, with DeviceDetector as a fallback. Requests with no User-Agent are flagged as bots.

Device

$request->deviceType();  // 'desktop', 'mobile', 'tablet', 'tv'
$request->isMobile();    // true/false
$request->isTablet();    // true/false
$request->isDesktop();   // true/false
$request->isTv();        // true/false
$request->deviceBrand(); // 'Apple'
$request->deviceModel(); // 'iPhone'

Browser

$request->browser();        // 'Chrome 120.0'
$request->browserName();    // 'Chrome'
$request->browserVersion(); // '120.0'
$request->browserFamily();  // 'Chrome'
$request->browserData();    // full parsed array

OS

$request->os();        // 'Mac 10.15'
$request->osName();    // 'Mac'
$request->osVersion(); // '10.15'
$request->osFamily();  // 'Mac'
$request->osData();    // full parsed array

Language

$request->language();  // 'en_US' (from X-LANG header, falls back to Accept-Language)
$request->languages(); // ['en_US', 'en', 'de'] (from Accept-Language)

Request Overrides

$request->getClientIp(); // prioritizes X-IP > CF-Connecting-IP > standard
$request->asn();         // 13335 (Autonomous System Number)
$request->userAgent();   // prioritizes X-AGENT > User-Agent
$request->referer();     // prioritizes X-REFERER > Referer
$request->refererDomain(); // 'google.com' (parsed from referer)

Cloudflare

$request->detectCloudflare(); // true if CF-ray header is present
$request->getHeader('X-CUSTOM'); // read any header

Artisan Commands

Command Description
cf-request:install Publish config and register service provider
cf-request:headers Create transform rule headers on Cloudflare via the API
cf-request:status Check which headers are configured on Cloudflare

Debug Route

Visit /cf-request/status in your browser to see all parsed headers as JSON. Disable with CF_ALLOW_STATUS_VIEW=false in your .env.

Changelog

See CHANGELOG for recent changes.

Credits

License

The MIT License (MIT). See License File for details.