$request->query() vs $request->input() in Laravel — What's the Difference?
If you've ever pulled a value from a request in Laravel and gotten back null — or the wrong value — there's a good chance you reached for the wrong method. Laravel gives you two very similar-looking ways to read incoming data: $request->query() and $request->input(). They look interchangeable, but they read from different parts of the request, and mixing them up causes silent bugs that are painful to track down.
Here's the difference, when to use each, and copy-paste examples so you always pick the right one.
The short answer
$request->query() reads from the URL query string only (the ?key=value part). Use it for GET parameters — filters, search, sorting, and pagination.
$request->input() reads from the query string and the request body (form or JSON). Use it for data submitted through POST, PUT, or PATCH requests.
The one-line rule: query() is for the URL, input() is for everything.
$request->query() explained
query() only ever looks at the query string — the part of the URL after the ?. It completely ignores the request body.
Given a request to /products?search=laravel&page=2:
public function index(Request $request)
{
$search = $request->query('search'); // "laravel"
$page = $request->query('page'); // "2"
// Provide a default when the parameter is missing
$sort = $request->query('sort', 'newest'); // "newest"
// Call it with no arguments to get the entire query string as an array
$all = $request->query();
// ['search' => 'laravel', 'page' => '2']
}
Because it's scoped to the URL, query() is the safest, most explicit choice for anything that belongs in a query string: search terms, filters, sort options, and pagination.
$request->input() explained
input() is broader. It reads from the entire request payload — form fields, JSON body, and the query string as a fallback. That flexibility is exactly why it's the go-to for form submissions and API endpoints.
Given a POST request with a JSON or form body of { "email": "hi@example.com", "plan": "pro" }:
public function store(Request $request)
{
$email = $request->input('email'); // "hi@example.com"
$plan = $request->input('plan', 'free'); // "pro", or "free" if missing
// Dot notation works for nested JSON / arrays
$city = $request->input('address.city');
}
Because input() also falls back to the query string, it "just works" in a lot of cases — which is exactly what makes the next section important.
Side by side: same request, different results
Here's the moment that trips people up. Imagine a PUT request to:
/users/5?role=guest
…with a body of role=admin.
$request->query('role'); // "guest" — from the URL
$request->input('role'); // "admin" — body wins over the query string
Same key, two different answers. query() gives you what's in the URL. input() gives you the body value, because when a key exists in both places, the request body takes precedence. If you assumed both would return the same thing, you now have a role-escalation bug hiding in plain sight.
When to use which
Reach for query() when the data legitimately belongs in the URL:
Search terms and filters (
?search=,?status=active)Sorting (
?sort=price&direction=asc)Pagination (
?page=2)
Reach for input() when the data comes from a form or an API client:
Creating or updating records (POST, PUT, PATCH)
JSON API payloads
Anything submitted in the request body
When you care where the value came from — for security-sensitive fields especially — be explicit and use query() so a request body can't override it.
Common mistakes to avoid
Using input() for a GET filter. It usually works, but it opens the door to body values sneaking in on an endpoint you thought was URL-only. Use query() and remove the ambiguity.
Forgetting default values. Both methods accept a second argument for a fallback. $request->query('page', 1) is cleaner and safer than checking for null yourself.
Confusing has() and filled(). $request->has('name') is true even when the value is an empty string. $request->filled('name') is only true when the value is present and not empty. Use filled() when an empty value should count as "missing."
Wrapping up
The difference comes down to one thing: query() reads only the URL, while input() reads the whole request and lets the body win. Use query() for filters, search, sorting, and pagination; use input() for form and API submissions — and be explicit whenever the source actually matters.
If you want to go deeper on how Laravel handles the different HTTP verbs behind these requests, check out my post on the HTTP query method in Laravel. Up next, I'll cover how to correctly handle GET, POST, PUT, and PATCH requests inside your Laravel routes — the natural next step once you know where your data is coming from.
