Reader Stacks

How to Get Request Headers in Laravel

Header names are matched case-insensitively — $request->header('Content-Type') and $request->header('content-type') both work identically, since the HTTP spec itself never treats header casing as meaningful.

How to Get Request Headers in Laravel

Reading HTTP request headers in Laravel — for a custom API key, checking the content type, or reading a client-provided token — goes through the Request object's header() method and a couple of related convenience checks.

Getting a specific header

$apiKey = $request->header('X-Api-Key');

Getting a header with a default fallback value

$locale = $request->header('Accept-Language', 'en');

Header names are matched case-insensitively

$request->header('Content-Type');
$request->header('content-type'); // returns the exact same value

HTTP headers are case-insensitive by specification — Laravel's header() method reflects this correctly, so it doesn't matter whether the header is checked using its conventional capitalization or an all-lowercase (or any other casing) version of the same name.

Getting every header at once

$allHeaders = $request->headers->all();

This returns an array of every header sent with the request — genuinely useful for debugging exactly what a client actually sent, though $allHeaders' values are each returned as an array (since a header can technically repeat with multiple values), not a plain string, unlike the single-header header() method.

Checking if a header exists at all

if ($request->hasHeader('X-Api-Key')) {
    // header was present
}

Reading the Bearer token from an Authorization header

$token = $request->bearerToken();

bearerToken() is a dedicated convenience method that specifically parses an Authorization: Bearer {token} header and returns just the token portion — simpler and less error-prone than manually reading the raw Authorization header and stripping the "Bearer " prefix with string manipulation.

Checking the request's expected content type

if ($request->expectsJson()) {
    return response()->json(['error' => 'Not found'], 404);
}

return response()->view('errors.404', [], 404);

expectsJson() checks the Accept header (along with whether the request is AJAX) to determine if the client wants a JSON response rather than an HTML page — genuinely useful for one route or error handler that needs to correctly serve both a browser-based frontend and a JSON API consumer.

Setting a custom header on the outgoing response

return response('Hello')->header('X-Custom-Header', 'some-value');

// Setting multiple headers at once
return response('Hello')->withHeaders([
    'X-Custom-Header' => 'some-value',
    'X-Another-Header' => 'another-value',
]);

A common real use case: validating a webhook's signature header

public function handleWebhook(Request $request)
{
    $signature = $request->header('X-Webhook-Signature');
    $expected = hash_hmac('sha256', $request->getContent(), config('services.webhook.secret'));

    if (! hash_equals($expected, $signature)) {
        abort(403, 'Invalid webhook signature.');
    }

    // process the verified webhook
}

hash_equals(), rather than a plain === comparison, is used deliberately here — it performs a timing-safe comparison, which prevents a timing-attack side channel that could otherwise be used to guess the correct signature one character at a time by measuring how long each incorrect guess takes to reject.