← Back to Blog
LaravelPHPBot DetectionMiddlewareBackend SecurityWeb Development

Bot Detection for Laravel: The Complete 2026 Guide

·12 min read·Device.AI Engineering

Why Laravel Apps Need Bot Detection

Laravel powers millions of modern web applications, APIs, and SaaS platforms. Built with elegance and developer productivity in mind, Laravel handles mission-critical application logic: user authentication, e-commerce checkouts, lead capture forms, API gateways, and community discussions. However, without automated bot detection, Laravel applications are primary targets for automated abuse:

  • Credential Stuffing & Brute-Force: Attackers rotate millions of leaked username/password combos against /login and authentication routes using headless browsers and proxy pools.
  • Scraping & Data Harvesting: Automated scripts and bots scrape proprietary pricing, catalog data, real estate listings, and user directories directly from Blade templates or Eloquent JSON API responses.
  • Fake Registrations & Account Creation: Spambots flood /register endpoints to create disposable accounts, claim trial resources, abuse promo codes, or spam community features.
  • Form Spam & Abuse: Contact forms, lead capture forms, and comment sections get saturated with SEO link spam, phishing payloads, and automated junk.
  • Card Testing: Fraud networks test stolen credit card numbers against Laravel cashier or custom payment checkout flows, resulting in costly chargebacks and payment processor penalties.

While Laravel provides basic rate limiting out of the box via RateLimiter, standard IP rate limits are ineffective against distributed proxy networks and residential IP rotation. This guide demonstrates how to integrate Device.AI into Laravel in under 5 minutes to identify and block bots with high accuracy before they hit your database or business logic.

How Bot Detection Works with Device.AI

Device.AI provides an ultra-low latency bot detection API. Your Laravel application passes request context (client IP address, User-Agent, and HTTP request headers) to Device.AI's POST /v1/verify endpoint. Device.AI evaluates behavioral signals, IP reputation, browser fingerprints, and automation indicators, returning a risk score between 0.0 (definite bot) and 1.0 (definite human).

You can then inspect the score directly in your Laravel middleware or Form Requests to block malicious traffic with HTTP 403, trigger challenge workflows, or rate-limit suspicious actors.

Step 1: Get Your Free API Key (1 Minute)

Visit device.ai and click "Get Free API Key". No credit card or lengthy onboarding is required. Your API key includes 1,000 free daily verifications immediately.

Your API key looks like:

dv_live_abc123def456ghi789jkl

Add it to your Laravel .env file:

DEVICE_AI_API_KEY=dv_live_abc123def456ghi789jkl
DEVICE_AI_TIMEOUT=2

And register it in config/services.php:

// config/services.php
return [
    // ...
    'device_ai' => [
        'key' => env('DEVICE_AI_API_KEY'),
        'url' => env('DEVICE_AI_URL', 'https://device.ai/v1/verify'),
        'timeout' => env('DEVICE_AI_TIMEOUT', 2),
    ],
];

Step 2: Create a Device.AI Service Class

Create a dedicated service class in your Laravel application using Laravel's built-in Http client:

<?php

namespace App\Services;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Throwable;

class DeviceAIService
{
    protected string $apiKey;
    protected string $verifyUrl;
    protected int $timeout;

    public function __construct()
    {
        $this->apiKey = (string) config('services.device_ai.key');
        $this->verifyUrl = (string) config('services.device_ai.url', 'https://device.ai/v1/verify');
        $this->timeout = (int) config('services.device_ai.timeout', 2);
    }

    /**
     * Verify an incoming request with Device.AI.
     */
    public function verify(Request $request, float $threshold = 0.5): array
    {
        // Fail open if API key is not configured
        if (empty($this->apiKey)) {
            return [
                'score' => 0.7,
                'is_bot' => false,
                'confidence' => 0,
                'error' => 'API key not configured',
            ];
        }

        try {
            $payload = [
                'ip' => $request->ip(),
                'user_agent' => $request->userAgent(),
                'headers' => $this->extractHeaders($request),
            ];

            $response = Http::withToken($this->apiKey)
                ->timeout($this->timeout)
                ->post($this->verifyUrl, $payload);

            if ($response->successful()) {
                $data = $response->json();
                $score = (float) ($data['score'] ?? 0.7);

                return [
                    'score' => $score,
                    'confidence' => (float) ($data['confidence'] ?? 0),
                    'is_bot' => $score < $threshold,
                    'error' => null,
                ];
            }

            Log::warning('Device.AI verification failed with HTTP status: ' . $response->status());
            return [
                'score' => 0.7,
                'is_bot' => false,
                'confidence' => 0,
                'error' => 'Upstream verification non-200',
            ];
        } catch (Throwable $e) {
            // Fail-open: Never let a verification network error bring down your Laravel application
            Log::error('Device.AI verification exception: ' . $e->getMessage());
            return [
                'score' => 0.7,
                'is_bot' => false,
                'confidence' => 0,
                'error' => $e->getMessage(),
            ];
        }
    }

    protected function extractHeaders(Request $request): array
    {
        return [
            'Accept-Language' => $request->header('accept-language'),
            'Accept-Encoding' => $request->header('accept-encoding'),
            'Referer' => $request->header('referer'),
            'Sec-Ch-Ua' => $request->header('sec-ch-ua'),
            'Sec-Ch-Ua-Mobile' => $request->header('sec-ch-ua-mobile'),
            'Sec-Ch-Ua-Platform' => $request->header('sec-ch-ua-platform'),
        ];
    }
}

Step 3: Create Laravel Bot Detection Middleware

Generate middleware to guard sensitive routes and endpoints:

php artisan make:middleware DetectBots

Implement the middleware logic with configurable thresholds:

<?php

namespace App\Http\Middleware;

use App\Services\DeviceAIService;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class DetectBots
{
    protected DeviceAIService $deviceAI;

    public function __construct(DeviceAIService $deviceAI)
    {
        $this->deviceAI = $deviceAI;
    }

    /**
     * Handle an incoming request.
     */
    public function handle(Request $request, Closure $next, float $threshold = 0.5): Response
    {
        $result = $this->deviceAI->verify($request, $threshold);

        // Attach the score and metadata to the request for use in controllers
        $request->attributes->set('device_ai', $result);

        if ($result['is_bot']) {
            if ($request->expectsJson()) {
                return response()->json([
                    'error' => 'Access denied: automated activity detected',
                    'score' => $result['score'],
                ], 403);
            }

            abort(403, 'Automated activity detected. Access denied.');
        }

        $response = $next($request);

        // Optionally append bot verification header for observability
        $response->headers->set('X-Bot-Score', (string) $result['score']);

        return $response;
    }
}

Step 4: Register and Apply the Middleware

In Laravel 11+, register the middleware alias in bootstrap/app.php:

// bootstrap/app.php (Laravel 11+)
use App\Http\Middleware\DetectBots;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        api: __DIR__.'/../routes/api.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function ($middleware) {
        $middleware->alias([
            'bot.detect' => DetectBots::class,
        ]);
    })
    ->create();

For Laravel 9 and 10, register the alias in app/Http/Kernel.php:

// app/Http/Kernel.php (Laravel 9/10)
protected $middlewareAliases = [
    // ...
    'bot.detect' => \App\Http\Middleware\DetectBots::class,
];

Now protect critical routes in routes/web.php or routes/api.php:

use App\Http\Controllers\AuthController;
use App\Http\Controllers\CheckoutController;
use App\Http\Controllers\CommentController;

// Strict threshold for authentication endpoints
Route::post('/login', [AuthController::class, 'login'])
    ->middleware('bot.detect:0.6');

// Protection for registration
Route::post('/register', [AuthController::class, 'register'])
    ->middleware('bot.detect:0.5');

// Strict threshold for payments and checkouts
Route::post('/checkout', [CheckoutController::class, 'process'])
    ->middleware('bot.detect:0.7');

// Loose threshold for public comments
Route::post('/comments', [CommentController::class, 'store'])
    ->middleware('bot.detect:0.3');

Step 5: Score Interpretation Table

Score RangeClassificationRecommended Action
0.0 - 0.3High confidence botBlock immediately (HTTP 403)
0.3 - 0.6Suspicious / AmbiguousChallenge (2FA prompt, CAPTCHA fallback)
0.6 - 1.0Likely humanAllow request through

Step 6: Production Best Practices for Laravel

1. Score Caching with Laravel Cache

To keep latency under 1ms for returning legitimate clients and reduce external API calls, cache verification scores using Laravel's cache facade (Redis or Memcached):

use Illuminate\Support\Facades\Cache;

$cacheKey = 'device_ai_score:' . $request->ip();

$result = Cache::remember($cacheKey, now()->addMinutes(5), function () use ($request, $threshold) {
    return $this->deviceAI->verify($request, $threshold);
});

2. Fail-Open Architecture

Security services should protect your app, not become a single point of failure. If the Device.AI service is momentarily unreachable or times out, your middleware should allow the request to proceed while logging the warning, rather than throwing a 500 error to your real users.

3. Combining with Laravel RateLimiter

Device.AI complements Laravel's rate limiter. You can dynamically adjust rate limits based on the bot score:

use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Cache\RateLimiting\Limit;

$score = $request->attributes->get('device_ai')['score'] ?? 0.7;
$maxAttempts = $score < 0.5 ? 5 : 60; // 5 attempts for suspicious traffic, 60 for verified humans

RateLimiter::for('api', function (Request $request) use ($maxAttempts) {
    return Limit::perMinute($maxAttempts)->by($request->ip());
});

Pricing and Free Tier

PlanDaily VerificationsPriceBest For
Free1,000$0Development, side projects, small apps
Pay-as-you-goUnlimited$0.001 per verificationGrowing Laravel SaaS & APIs
EnterpriseCustomCustom pricingHigh-traffic platforms, dedicated SLA

Next Steps

  1. Get your free API key at device.ai (1 minute, no credit card required)
  2. Add DEVICE_AI_API_KEY to your Laravel .env file
  3. Create the DeviceAIService and DetectBots middleware
  4. Apply bot.detect middleware to your login, registration, and payment routes
  5. Review your request logs and tune thresholds based on traffic characteristics

Resources

Questions or need integration support? Contact support@device.ai.

Ready to stop bots?

Get a free API key instantly. No signup, no credit card.

Get Free API Key →