URL Parameters vs Query Strings in Express.js
When a request arrives at your Express server, the URL carries more information than just a destination.
Tucked inside the URL are often pieces of data your server needs to do its job: which user to look up, what search term to apply, how many results to return. Two mechanisms handle this job, and they look similar at a glance but serve very different purposes.
URL parameters and query strings are both ways of passing data through a URL. Understanding what each one is for, and when to reach for one over the other, makes your routes cleaner and your API more intuitive.
What URL Parameters Are
A URL parameter is a dynamic segment embedded directly in the URL path. It is part of the route structure itself, not an addition to it.
In Express, you define a URL parameter by placing a colon before a name in the route path:
/users/:id
When a request comes in for /users/42, Express recognizes that 42 is the value for the :id parameter. The route matches, and your handler receives the value. Change the URL to /users/99 and the same route handles it, this time with 99 as the ID.
URL parameters are identifiers. They point to a specific resource. The parameter is not a filter or a modifier, it is a locator. Think of it as the address of a thing, not a description of how you want that thing.
What Query Parameters Are
Query parameters live at the end of a URL, after a question mark. Each parameter is a key-value pair, and multiple parameters are separated by ampersands:
/products?category=shoes&sort=price&limit=20
Unlike URL parameters, query strings are not part of the route definition. Express does not need to know in advance what query parameters a request might include. They arrive as optional additions that your handler can read or ignore entirely.
Query parameters are modifiers. They describe how you want to interact with a resource rather than which resource you want. A search term, a sorting preference, a page number, a filter by date: these are all natural fits for query strings.
Differences Between URL Parameters and Query Strings
The distinction comes down to structure and intent.
URL parameters are baked into the path. They are required for the route to match at all. If your route is /users/:id and a request comes in for /users/ with no ID, the route does not match. The parameter is not optional, it is part of the address itself.
Query strings sit outside the path structure. They are optional by nature. A request to /products and a request to /products?sort=price hit the same route. Your handler can check whether a query parameter exists and behave differently based on whether it is there, but the absence of a query parameter never breaks a route match.
Here is a simple way to hold the difference in mind. URL parameters answer the question "which one?" Query strings answer the question "how?"
Accessing URL Parameters in Express
Express stores URL parameter values in the req.params object. Each named segment in your route becomes a key in that object.
app.get("/users/:id", (req, res) => {
const userId = req.params.id;
res.send("Fetching user with ID: " + userId);
});
A request to /users/42 gives you req.params.id equal to "42". Note that Express gives you the value as a string. If you need to use it as a number, convert it explicitly.
You can also have multiple parameters in a single route:
app.get("/teams/:teamId/members/:memberId", (req, res) => {
const { teamId, memberId } = req.params;
res.send(`Team \({teamId}, Member \){memberId}`);
});
Each named segment maps to its own key in req.params.
Accessing Query Strings in Express
Query string values live in req.query. Express automatically parses the query string and makes each key-value pair available as a property.
app.get("/products", (req, res) => {
const category = req.query.category;
const sort = req.query.sort;
const limit = req.query.limit;
res.send(`Category: \({category}, Sort: \){sort}, Limit: ${limit}`);
});
A request to /products?category=shoes&sort=price&limit=20 gives you req.query.category as "shoes", req.query.sort as "price", and req.query.limit as "20".
Just like URL parameters, all values come through as strings. If you are using a limit as a number in your logic, parse it before using it.
Query parameters are optional, so it is good practice to check whether they exist before relying on them. You can set defaults for missing values to keep your logic predictable:
const limit = req.query.limit || 10;
const sort = req.query.sort || "created_at";
When to Use Parameters vs Query Strings
Use URL parameters when the value identifies a specific resource. A user profile, a blog post, a product listing, an order: anything that has a unique identity and your route needs to locate it precisely.
GET /users/42
GET /posts/intro-to-express
GET /orders/ORD-8821
These URLs read naturally. The parameter is part of the resource address, not a filter on top of it.
Use query strings when the value modifies how a collection or resource is returned. Searching, filtering, sorting, and pagination are the classic cases.
GET /products?category=shoes
GET /articles?author=jane&published=true
GET /users?page=2&limit=25
GET /posts?search=javascript&sort=recent
These URLs describe a set of results shaped by the parameters, not a single specific item.
A common pattern combines both. The URL parameter identifies which collection or parent resource you are working with, and the query string filters within it:
GET /categories/electronics/products?sort=price&limit=10
Here :category (electronics) is a specific resource being addressed. The query string then shapes how the products within that category are returned.
Wrapping Up
URL parameters and query strings both carry data through a URL, but they have distinct roles that are worth respecting. Parameters locate things. Query strings describe things.
Keeping this distinction clear makes your routes more readable and your API more predictable. A developer looking at your endpoints should be able to tell at a glance whether a piece of data identifies a resource or modifies a request. URL parameters and query strings, used correctly, make that obvious without any explanation needed.
You are all set!
written by theadroitdev(Shivam Verma) :)
๐ โ https:/theadroitdev.com/
X โ https://x.com/theadroitdev
Github โ https://github.com/TheAdroitDev
ChaiCode Repo โ https://github.com/TheAdroitDev/ChaiCode-Cohort-2026


