Query parameters are key-value pairs appended to a URL after the ? character, used to filter, sort, paginate, or modify API responses. They provide a flexible way to customize requests without changing the endpoint structure.
Query Parameters
Key-value pairs appended to URLs for filtering, sorting, and customizing API requests.
Syntax and Structure
Basic format: /users?status=active&limit=10
?starts the query stringkey=valuepairs define parameters&separates multiple parameters- Values must be URL-encoded (spaces become
%20or+)
Multiple values: /products?category=electronics&category=books or /products?category=electronics,books
Common Use Cases
| Purpose | Example | Description |
|---|---|---|
| Filtering | ?status=active | Return only matching records |
| Sorting | ?sort=created_at&order=desc | Order results |
| Pagination | ?page=2&limit=20 | Navigate through results |
| Search | ?q=search+term | Full-text search |
| Field selection | ?fields=id,name,email | Return only specific fields |
| Include relations | ?include=posts,comments | Expand related data |
Query Params vs Path Params
Path parameters identify specific resources:
GET /users/123 - Get user with ID 123
Query parameters modify the response:
GET /users?status=active - Get all active users
Rule of thumb:
- Path params for required identifiers
- Query params for optional filters/modifiers
Designing Query Parameters
Be consistent:
Pick a convention and stick to it. sort_by or sortBy, not both.
Use intuitive names:
?limit=10 not ?l=10. Readability over brevity.
Document defaults: What happens when parameter is omitted? Document it.
Validate inputs: Reject invalid values with clear error messages.
Set sensible limits:
?limit=10000 could crash your server. Cap it.
Pagination Patterns
Offset-based:
?page=2&limit=20 or ?offset=20&limit=20
Simple but slow for large offsets (database must skip rows).
Cursor-based:
?cursor=abc123&limit=20
Fast for large datasets. Cursor is usually encoded ID or timestamp.
Choose cursor when:
- Large datasets (100k+ records)
- Real-time data (items added frequently)
- Infinite scroll UI
Filtering Best Practices
Range filters:
?price_min=10&price_max=100 or ?price[gte]=10&price[lte]=100
Multiple values:
?status=active,pending (comma-separated) or ?status[]=active&status[]=pending (array syntax)
Null checks:
?deleted_at=null or ?deleted_at[is]=null
Nested filtering:
?user.role=admin or ?filter[user][role]=admin
Security Considerations
SQL Injection: Never concatenate query params directly into SQL. Use parameterized queries.
Sensitive data: Query params appear in logs, browser history, referrer headers. Don't pass passwords or tokens.
Mass assignment: Don't blindly pass all query params to database queries. Whitelist allowed fields.
DoS prevention: Limit maximum page size, search complexity, and number of filters.
Common Mistakes
1. Inconsistent naming:
sortBy on one endpoint, sort_by on another. Pick one convention.
2. No validation:
?limit=abc should return 400, not crash.
3. Missing defaults: What's the default sort order? Document and handle it.
4. Case sensitivity:
?Status=Active vs ?status=active. Be explicit about case handling.
5. Ignoring URL length limits: URLs over 2048 chars may fail. Use POST with body for complex queries.
Code Examples
Parsing and Validating Query Parameters
// Express route with query parameter handling
app.get('/products', (req, res) => {
// Parse with defaults
const page = Math.max(1, parseInt(req.query.page) || 1);
const limit = Math.min(100, parseInt(req.query.limit) || 20);
const sortBy = ['price', 'name', 'created_at'].includes(req.query.sort)
? req.query.sort
: 'created_at';
const order = req.query.order === 'asc' ? 'asc' : 'desc';
// Parse array filters
const categories = req.query.category
? [].concat(req.query.category)
: [];
// Build query
const offset = (page - 1) * limit;
const products = await db.products.findMany({
where: categories.length
? { category: { in: categories } }
: undefined,
orderBy: { [sortBy]: order },
skip: offset,
take: limit
});
res.json({
data: products,
pagination: { page, limit, total: await db.products.count() }
});
});Related Terms
Mock API
A simulated API endpoint that returns predefined responses for testing and development.
HTTP Status Codes
Standard response codes that indicate the result of an HTTP request.
CORS
Cross-Origin Resource Sharing - A security mechanism that controls how web pages can request resources from different domains.
Idempotency
A property where making the same API request multiple times produces the same result.