Skip to content

pdphilip/cf-request

Repository files navigation

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.

About

Cloudflare Laravel Request enriches the standard Laravel HTTP Request with Location, Timezone and Bot/Threat information from Cloudflare, as well as the user's Device type, OS and Browser

Resources

License

Stars

Watchers

Forks

Sponsor this project

Packages

 
 
 

Contributors

Languages