URL Parameters vs Query Strings in Express.js

Your API needs to receive data from users. Express lets you pass data through the URL in two different ways: URL parameters and query strings. They look different, work differently, and have different purposes.
URL Parameters: Part of the Route
URL parameters are placeholders in the route path. They're required and define the resource you're accessing.
Consider these examples:
/users/123 - get user with ID 123
/posts/456/comments - get comments for post 456
/products/789/reviews - get reviews for product 789
The numbers and identifiers are URL parameters. They identify which specific resource you want.
In Express, you define parameters with a colon:
import express from 'express';
const app = express();
app.get('/users/:id', (req, res) => {
const userId = req.params.id;
res.json({ message: `Getting user ${userId}` });
});
app.get('/posts/:postId/comments/:commentId', (req, res) => {
const postId = req.params.postId;
const commentId = req.params.commentId;
res.json({ postId, commentId });
});
app.listen(3000);
When a request comes in, Express extracts the parameter values and places them in req.params.
Usage examples:
GET /users/123→req.params.id="123"GET /posts/456/comments/789→req.params.postId="456",req.params.commentId="789"
Query Strings: Optional Filters and Options
Query strings come after a question mark in the URL. They're optional and add filtering or modification options.
Consider these examples:
/users?role=admin - filter users by role
/products?sort=price&limit=10 - sort by price, limit to 10 results
/search?q=node&lang=en - search for "node" in English
In Express, query strings are available in req.query:
import express from 'express';
const app = express();
app.get('/users', (req, res) => {
const role = req.query.role;
const status = req.query.status;
res.json({ message: `Getting users`, role, status });
});
app.get('/search', (req, res) => {
const q = req.query.q;
const limit = req.query.limit;
res.json({ search: q, limit });
});
app.listen(3000);
Usage examples:
GET /users?role=admin→req.query.role="admin"GET /search?q=javascript&limit=20→req.query.q="javascript",req.query.limit="20"
Parameters vs Query Strings: Key Differences
| Aspect | URL Parameters | Query Strings |
|---|---|---|
| Purpose | Identify resource | Filter/modify results |
| Required | Yes | No |
| Syntax | /users/123 |
/users?role=admin |
| Express | req.params |
req.query |
| Example | Get specific user | Get users matching criteria |
| Multiple values | Hard to add | Easy with & |
Real-World Examples
URL Parameters: Identify the exact resource you want
app.get('/users/:id', (req, res) => {
// GET /users/123
// Retrieve THE user with ID 123
});
app.get('/posts/:postId/comments/:commentId', (req, res) => {
// GET /posts/456/comments/789
// Get specific comment 789 in specific post 456
});
Query Strings: Filter or modify what you're retrieving
app.get('/users', (req, res) => {
// GET /users?role=admin&status=active
// Get all users, but filter by role and status
});
app.get('/posts', (req, res) => {
// GET /posts?sort=date&limit=10&skip=20
// Get posts, sorted by date, 10 per page, starting from position 20
});
Combining Both
You can use both parameters and query strings together:
import express from 'express';
const app = express();
app.get('/users/:id/posts', (req, res) => {
const userId = req.params.id;
const sort = req.query.sort;
const limit = req.query.limit;
res.json({
message: `Getting posts for user ${userId}`,
sort,
limit
});
});
app.listen(3000);
Examples:
GET /users/123/posts→ User 123's postsGET /users/123/posts?sort=date→ User 123's posts sorted by dateGET /users/123/posts?sort=date&limit=10→ User 123's 10 most recent posts
Multiple Query Parameters
When you have multiple query parameters, separate them with &:
app.get('/search', (req, res) => {
const query = req.query.q;
const lang = req.query.lang;
const category = req.query.category;
res.json({ query, lang, category });
});
Usage:
GET /search?q=javascript&lang=en&category=tutorial
→ query = "javascript", lang = "en", category = "tutorial"
Query Parameters with Arrays
You can pass multiple values for the same parameter:
app.get('/products', (req, res) => {
const colors = req.query.color;
res.json({ colors });
});
Usage:
GET /products?color=red&color=blue&color=green
→ colors = ["red", "blue", "green"]
Type Conversion
Query parameters always come as strings. If you need numbers, convert them:
import express from 'express';
const app = express();
app.get('/products', (req, res) => {
const limit = parseInt(req.query.limit) || 10;
const skip = parseInt(req.query.skip) || 0;
res.json({ limit, skip });
});
app.listen(3000);
Without conversion, req.query.limit is the string "20", not the number 20.
When to Use Each
Use URL parameters when:
Identifying a specific resource
The value is required
Following REST principles for resource identification
Examples: user ID, post ID, product ID
Use query strings when:
Filtering results
Sorting or paginating
The value is optional
Adding modifiers or options
Examples: role, category, sort order, page number
REST API Best Practices
A well-designed REST API uses both appropriately:
import express from 'express';
const app = express();
// Get all users (with optional filters)
app.get('/users', (req, res) => {
const role = req.query.role;
const status = req.query.status;
// Retrieve users, optionally filtered by role and status
});
// Get specific user
app.get('/users/:id', (req, res) => {
const userId = req.params.id;
// Retrieve specific user by ID
});
// Get posts for a specific user (with optional sorting)
app.get('/users/:userId/posts', (req, res) => {
const userId = req.params.userId;
const sort = req.query.sort;
// Retrieve posts for user, optionally sorted
});
// Get specific comment on specific post by specific user
app.get('/users/:userId/posts/:postId/comments/:commentId', (req, res) => {
const { userId, postId, commentId } = req.params;
// Retrieve specific comment
});
app.listen(3000);
Common Mistakes
Mistake 1: Using parameters when query strings make sense
// Wrong - parameters for filters
app.get('/users/:role/:status', (req, res) => {
// URL becomes /users/admin/active
// Hard to add more filters
});
// Better - query strings for filters
app.get('/users', (req, res) => {
// URL is /users?role=admin&status=active
// Easy to add/remove filters
});
Mistake 2: Forgetting to convert query parameters to numbers
app.get('/products', (req, res) => {
const limit = req.query.limit; // This is a string!
const results = db.getProducts().slice(0, limit);
// limit as string might not slice correctly
});
Key Takeaways
URL parameters identify a specific resource and go in the route path
Query strings are optional filters and go after the question mark
Parameters are required and part of the route definition
Query strings are optional and make URLs flexible
Access parameters via
req.paramsand query strings viareq.queryCombine both for powerful, flexible APIs
Use parameters for identification, query strings for filtering
Mastering both gives you the tools to build flexible, standard REST APIs that users can intuitively understand.




