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
API Versioning
Strategies for managing breaking changes in APIs while maintaining backward compatibility.
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.
API Testing
The process of verifying that APIs work correctly, securely, and perform well.