Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Browscap Laravel Package

propa/laravel-browscap

Laravel integration for browscap that identifies browser name, version, platform, device type, and crawler status from a user agent string using the browscap data files.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package and its underlying engine:

composer require propa/laravel-browscap

Laravel 5.5+ auto-discovers Propa\Browscap\BrowscapServiceProvider. On older versions, register it in config/app.php and add the Browscap facade alias.

Publish the config file:

php artisan vendor:publish --provider="Propa\Browscap\BrowscapServiceProvider"

This produces config/browscap.php with the cache strategy, cache directory, and update_interval (default ~5 days). If you change settings, run php artisan config:clear.

The first use case is almost always request classification: knowing whether the current visitor is a bot, mobile, tablet, or desktop so you can branch logging, routing, or rendering.

use Propa\Browscap\Facades\Browscap;

$browser = Browscap::getBrowser(request()->userAgent());

$browser->getBrowser();      // "Chrome"
$browser->getVersion();      // "124.0"
$browser->getPlatform();     // "Windows"
$browser->isMobile();
$browser->isTablet();
$browser->isDesktop();
$browser->isBot();
$browser->getDeviceType();   // "Mobile", "Tablet", "Desktop", ...
$browser->getBrowserType();  // "Browser", "Bot/Crawler", "Application"

That single call is your entry point; everything else builds on it.

Implementation Patterns

Middleware for device class detection. The cleanest day-to-day integration is a middleware that resolves the user agent once per request and stores it on the request attributes so downstream code (controllers, views, logs) doesn't re-parse:

class DetectDevice
{
    public function handle($request, Closure $next)
    {
        $ua = $request->userAgent();
        $request->attributes->set('browser', $ua ? Browscap::getBrowser($ua) : null);
        return $next($request);
    }
}

Downstream, controllers read $request->attributes->get('browser') instead of re-querying the facade.

Analytics / audit logging. Browscap is ideal for enriching a visits or logins table. Store normalized fields (browser, browser_version, platform, device_type, is_bot) once at write time rather than on every read. Persisting the raw user agent alongside is cheap and lets you re-derive later.

Mobile redirect / separate views. In a middleware or route group, redirect mobile traffic to a m. subdomain or serve a mobile Blade layout. Keep the switch keyed on isMobile() plus an override cookie so users can force desktop view — otherwise you'll trap people who spoof or whose UA is misclassified.

Bot filtering. Use isBot() / getBrowserType() === 'Bot/Crawler' to skip analytics writes, rate-limit aggressively, or exclude from A/B experiments. Don't use it as a security control (see Gotchas).

Wrapping in a service for testability. Facade calls are static and painful to swap in tests. Bind a thin DeviceResolver interface around Browscap::getBrowser(), and in tests bind a fake that returns a hand-built Browser (or a simple DTO). This keeps feature tests fast and avoids the underlying engine's file/network behavior.

Queues and console commands. Browscap is safe to call from jobs, but remember that on a fresh deployment the first call may trigger a data-file download. Run a pre-warm job during deploy (see Gotchas) rather than letting a user hit that cold path.

Blade convenience. For view-level branching, either pass the resolved device type into the view from the middleware or add a Blade directive wrapping the same service — avoid calling the facade directly in templates since exceptions during data refresh will blank the page.

Gotchas and Tips

The first lookup is slow and needs network access. The engine downloads browscap.ini from browscap.org when the cache is stale or missing. In development this means a multi-second first request; in air-gapped/production environments this can hang or fail. Pre-warm after deployment or bake the cache into your image:

php artisan browscap:update   # if the package registers it
# or trigger once via a warm-up script/route

If no artisan command is available in your version, add a deploy step that instantiates Browscap::getBrowser('test') once per environment.

Read-only filesystems break the default cache. The default file cache writes under storage/. On Lambda, Heroku ephemeral dynos, or containers with read-only volumes you'll get permission/write errors. Switch cache to a Redis-backed option (requires the browscap/browscap-php Redis adapter and the phpredis extension) or to a writable persistent path.

Concurrent requests serialize on the cache lock. When the data file expires, many simultaneous requests can contend on the cache lock, producing latency spikes or timeouts. Mitigate by refreshing proactively (scheduled command/job during low traffic) and increasing update_interval only if you're comfortable with stale user-agent data.

update_interval is the refresh, not the cache TTL. Don't confuse it with response caching. The parsed results for individual user agents are still stored separately; the interval controls how often the underlying data file is re-fetched.

Config caching requires absolute paths. php artisan config:cache bakes the config, so cache_dir should be absolute (env-driven) rather than relying on a runtime base_path() call you change per deploy.

Null properties on unknown browsers. getVersion(), getPlatform(), and getDeviceType() can be null or "unknown" for unusual agents. Always null-coalesce before string operations or database inserts, and decide on a default (e.g., "Other") at the service layer.

User agents are user-controlled — treat browscap output as a hint, not truth. Never gate security, feature access, or pricing on UA-derived data. Bots lie. This is a categorization tool, not an authentication mechanism.

The facade resolves at call time, not boot time. That's fine for tests (you can Browscap::shouldReceive(...)), but if you inject the underlying Browser at constructor time in a service provider it'll be stale per request. Resolve inside the method.

Exception surface is thin. The wrapper largely passes through browscap/browscap-php exceptions (download errors, cache write errors). Wrap getBrowser() in a try/catch in any request-path integration and fall back to a neutral default so a data refresh failure doesn't 500 the site.

Testing. Browscap::shouldReceive('getBrowser')->andReturn($fakeBrowser) works, but the Browser class is from the upstream library and building fakes is awkward. The wrapper-service pattern mentioned above pays off here — test your DTO, not the library.

Small-project caveat. With only a handful of dependents and a low activity score, pin the version explicitly in composer.json ("propa/laravel-browscap": "^x.y") and check the upstream browscap/browscap-php release notes when upgrading — the Browser API surface you rely on comes from there, not from this wrapper.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core