rmunate/agent-detection
rmunate/agent-detection is a lightweight PHP/Laravel package that parses the User-Agent to identify the browser, operating system, device type, and whether a visitor is a bot or crawler. Simple, fast API with no external service calls.
Install the package via Composer:
composer require rmunate/agent-detection
There is almost no bootstrapping required — this is a lightweight detection library rather than a full framework extension. Start by reading the full documentation (linked prominently in the release notes), since the release notes intentionally omit the API surface and only describe capabilities at a high level.
First use case: personalize the landing experience based on connection type. In a controller or Blade view, resolve the agent once, then branch:
A second, equally common first task is bot/crawler/spider detection — useful for gating analytics, skipping heavy rendering, or serving a simplified response to automated traffic.
Where to look first:
src/) for the detection methods and any config file.php artisan vendor:publish) — check whether custom bot lists or UA overrides are configurable.Resolve once per request, reuse everywhere. Agent parsing is cheap but not free, and doing it repeatedly in a view loop is wasteful. Resolve the agent details in a controller, a view composer, or a small service, and pass the result down. If the package exposes a facade, the container will hand you the same resolved instance within a request — still, avoid calling detection methods inside tight loops.
Blade conditionals for device-aware UI.
@if ($agent->isMobile())
<a href="{{ $appStoreLink }}">Get the app</a>
@endif
Keep the branching shallow — one or two device checks per view. If you find yourself nesting isAndroid() / isiOS() / isDesktop() blocks, extract a partial per platform instead.
Middleware for bot handling. A middleware is the cleanest place to act on crawler detection:
public function handle($request, Closure $next)
{
if (AgentDetection::isBot()) {
// e.g. skip session persistence, serve a lightweight response,
// or tag the request for downstream logic
}
return $next($request);
}
Register it globally only if the behavior is genuinely universal; otherwise scope it to specific route groups.
Controller-level personalization. For richer logic (different menu structures, feature flags per platform), inject the detector into the controller and build a small view-model or DTO that the view consumes. This keeps device logic testable and out of templates.
Pair with Laravel's native request data. The package handles UA parsing; keep using $request->header('User-Agent'), $request->ip(), and Laravel's localization/Accept-Language handling for the surrounding context. Don't try to make the agent library do geo- or language-detection work.
Testing hook. Because detection reads the request's User-Agent, you can exercise branches in feature tests by sending crafted headers:
$this->withHeader('User-Agent', 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X)...')
->get('/')
->assertSee('App Store');
Build a small fixture set of UA strings (iPhone, Android, desktop Chrome, Googlebot) and reuse them across tests.
Never use detection for security decisions. User-Agent strings are trivially spoofed. Bot detection is a heuristic, not an access control — do not rely on isBot() to protect endpoints, rate-limit abuse, or authorize actions. Use it for UX and analytics shaping only.
Allowlist legitimate crawlers. Aggressive bot handling will happily block Googlebot, Bingbot, and your own uptime monitors. If you're serving different content or short-circuiting responses for detected bots, maintain an explicit allowlist (likely configurable — check the config file) before taking action.
Proxies and CDNs can rewrite or strip headers. If you sit behind a CDN or reverse proxy, the User-Agent reaching PHP may differ from what the client sent, and some setups strip it entirely. Verify detection behavior in your actual deployment topology, not just locally.
Pin expectations in tests, not assumptions. Since exact method names aren't documented in the release notes, confirm signatures against the docs/source before writing tests, and assert on behavior rather than trusting a single UA string. UA databases age — a UA that parses as "mobile" today may parse differently after a package update.
Watch for silent fallbacks. Detection libraries generally return a default (often "desktop" or "unknown") when parsing fails. Make sure your UI degrades gracefully for unknown agents rather than misclassifying them — treat "unknown" as its own branch where it matters.
Cache-bust on version bumps. If you cache rendered output keyed only by URL, device-specific variants can leak across users. Vary your cache key by the detected platform (or skip caching for personalized fragments).
Extension points to inspect: custom bot/crawler lists, any config-driven UA overrides, and whether the detector is swappable via the container (useful for faking results in tests). If the package ships a facade, you can AgentDetection::shouldReceive(...)-style mock it or bind a fake implementation rather than manipulating headers in every test.
Keep the dependency current. UA-parsing accuracy depends on the bundled rules; treat version updates as data refreshes and re-run your UA fixture tests after each bump.
How can I help you explore Laravel packages today?