How to access query string parameters in Express.js on Node.js?
Can we retrieve query string variables in Node.js similar to how we access them through $_GET in PHP?
I understand that Node.js provides access to the URL in the request object. What is the proper method to extract and access query string parameters in Express.js?
In Express.js, query string parameters are accessed through the req.query object, which automatically parses the URL query string into a JavaScript object containing key-value pairs. This is fundamentally different from PHP’s $_GET as it’s a native JavaScript object rather than a superglobal array, but provides similar functionality for accessing URL parameters. The Express framework handles all URL parsing automatically, making query parameter retrieval straightforward and consistent across different routes.
Contents
- Basic Query Parameter Access
- Handling Arrays and Multiple Values
- Advanced Validation and Best Practices
- Complete Examples and Implementation
- Comparison with PHP’s $_GET
Basic Query Parameter Access
Express.js provides the most straightforward method for accessing query string parameters through the req.query property. This property is automatically populated by Express when a request comes in, containing all the parsed query string parameters as key-value pairs in a JavaScript object.
The fundamental syntax is:
req.query.parameterName
For example, given a URL like http://localhost:3000/?name=John&age=25, the req.query object would contain:
{
name: "John",
age: "25"
}
You can access individual parameters directly:
const express = require("express");
const app = express();
app.get("/", function (req, res) {
res.send(`Your name is ${(req.query.name || "").length} characters long`);
});
app.listen(3000);
According to the official Express documentation, the req.query object is the result of parsing the URL query string, or an empty object if there is no query string. This approach is consistent across all Express route handlers.
Handling Arrays and Multiple Values
One of the powerful features of Express.js query parameter handling is its automatic support for arrays and multiple values. When a query parameter appears multiple times in the URL, Express automatically converts it into an array.
For example, with the query string ?color=black&color=yellow, the req.query object becomes:
{
color: ["black", "yellow"]
}
This behavior is demonstrated in the Mastering JS tutorial, which shows how Express handles multiple values for the same parameter name:
const app = require('express')();
app.get('*', (req, res) => {
req.query; // { color: ['black', 'yellow'] }
res.json(req.query);
});
When working with arrays, you should always check if the result is actually an array:
app.get('/fruits', (req, res) => {
const { filterBy = [] } = req.query;
console.log(Array.isArray(filterBy)); // true
// Now you can safely use array methods
const filteredItems = originalItems.filter(item => filterBy.includes(item.type));
res.json(filteredItems);
});
If you need to handle nested objects in query strings, Express also supports this through dot notation. For example, ?user[name]=John&user[age]=25 would result in:
{
user: {
name: "John",
age: "25"
}
}
Advanced Validation and Best Practices
While basic query parameter access is straightforward, production applications often require robust validation and sanitization of query parameters. The express-validator library provides comprehensive validation middleware specifically designed for this purpose.
Basic Validation with express-validator
const { checkSchema, validationResult } = require('express-validator');
app.get('/search', checkSchema({
query: {
in: 'query',
isString: true,
isLength: {
options: { min: 3 }
},
errorMessage: 'Search query must be at least 3 characters long'
},
limit: {
in: 'query',
isInt: {
options: { min: 1, max: 100 }
},
optional: true,
errorMessage: 'Limit must be between 1 and 100'
}
}), (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
// Proceed with validated parameters
const { query, limit = 10 } = req.query;
// ... your business logic
});
Schema-Based Validation
For more complex scenarios, schema-based validation offers a cleaner approach:
const { body, query, param } = require('express-validator');
const searchValidation = [
query('filterBy').isArray().withMessage('Filter must be an array'),
query('filterBy.*').isString().withMessage('Each filter must be a string')
];
app.get('/products', searchValidation, (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const { filterBy = [] } = req.query;
// Process array filters safely
});
As mentioned in the Scaler Topics guide, proper validation is crucial for building secure and reliable APIs. Key best practices include:
- Always validate user input - Never trust query parameters directly
- Set appropriate data types - Convert strings to numbers/booleans as needed
- Handle optional parameters gracefully - Provide default values
- Sanitize inputs - Remove potentially malicious content
- Validate array parameters - Ensure they conform to expected structure
Complete Examples and Implementation
Let’s explore a complete implementation that covers various scenarios for query parameter handling in Express.js.
Example 1: Basic Search Endpoint
const express = require('express');
const app = express();
// Search endpoint with multiple parameters
app.get('/api/search', (req, res) => {
const { q, category, limit = 10, page = 1 } = req.query;
// Basic validation
if (!q || q.trim() === '') {
return res.status(400).json({ error: 'Search query is required' });
}
// Convert limit and page to numbers
const limitNum = parseInt(limit, 10);
const pageNum = parseInt(page, 10);
// Validate numeric parameters
if (isNaN(limitNum) || limitNum < 1 || limitNum > 100) {
return res.status(400).json({ error: 'Limit must be between 1 and 100' });
}
if (isNaN(pageNum) || pageNum < 1) {
return res.status(400).json({ error: 'Page must be a positive number' });
}
// Process search logic here
const results = performSearch(q, category, limitNum, pageNum);
res.json({
query: q,
category,
page: pageNum,
limit: limitNum,
results
});
});
function performSearch(query, category, limit, page) {
// Your search implementation here
return [];
}
app.listen(3000, () => {
console.log('Server running on port 3000');
});
Example 2: Filtering with Arrays
app.get('/api/products', (req, res) => {
const {
categories = [],
priceRange,
sortBy = 'name',
sortOrder = 'asc'
} = req.query;
// Handle categories array
const categoryArray = Array.isArray(categories) ? categories : [categories].filter(Boolean);
// Parse price range
let minPrice = 0;
let maxPrice = Infinity;
if (priceRange) {
const prices = priceRange.split('-').map(p => parseFloat(p.trim()));
if (prices.length === 2 && !prices.some(isNaN)) {
minPrice = prices[0];
maxPrice = prices[1];
}
}
// Validate sort parameters
const validSortFields = ['name', 'price', 'rating'];
const validSortOrders = ['asc', 'desc'];
if (!validSortFields.includes(sortBy)) {
return res.status(400).json({ error: 'Invalid sort field' });
}
if (!validSortOrders.includes(sortOrder)) {
return res.status(400).json({ error: 'Invalid sort order' });
}
// Process filtering logic
const filteredProducts = filterProducts({
categories: categoryArray,
minPrice,
maxPrice,
sortBy,
sortOrder
});
res.json({
filters: {
categories: categoryArray,
priceRange: `${minPrice}-${maxPrice}`,
sortBy,
sortOrder
},
products: filteredProducts
});
});
Example 3: Using Middleware for Common Query Parameters
// Middleware to handle common pagination parameters
const paginateMiddleware = (req, res, next) => {
const { page = '1', limit = '10' } = req.query;
req.pagination = {
page: Math.max(1, parseInt(page, 10)),
limit: Math.min(100, Math.max(1, parseInt(limit, 10)))
};
next();
};
// Apply middleware to routes that need pagination
app.get('/api/users', paginateMiddleware, (req, res) => {
const { page, limit } = req.pagination;
const offset = (page - 1) * limit;
// Get users with pagination
const users = getUsers(limit, offset);
res.json({
page,
limit,
total: getTotalUsersCount(),
users
});
});
These examples demonstrate the flexibility and power of Express.js query parameter handling, from basic access to complex filtering and pagination scenarios.
Comparison with PHP’s $_GET
While both Express.js and PHP provide ways to access query string parameters, there are fundamental differences in their implementation and usage patterns.
Similarities
- Both allow access to URL query parameters
- Both support multiple values for the same parameter name
- Both provide key-value access to parameters
Key Differences
1. Data Type and Structure
- PHP
$_GET: Returns an array of strings, even for numeric values - Express
req.query: Returns a JavaScript object with proper type preservation (arrays remain arrays, numbers are strings unless converted)
2. Automatic Parsing
- PHP: Built-in superglobal that’s always available
- Express: Requires the Express framework and is available only within route handlers
3. Type Handling
- PHP: All parameters are strings by default
- Express: Maintains array structure when parameter names repeat
4. Access Pattern
// PHP
$name = $_GET['name'] ?? 'default';
$categories = $_GET['category'] ?? []; // Always an array
// Express.js
const name = req.query.name || 'default';
const categories = Array.isArray(req.query.category) ? req.query.category : [req.query.category].filter(Boolean);
5. Validation Requirements
- PHP: Often requires manual validation and type casting
- Express.js: Can leverage JavaScript’s dynamic typing and modern validation libraries
The Stack Overflow discussion provides practical examples of how Express.js query parameter access compares to traditional web frameworks.
Despite these differences, the core concept remains the same: both systems provide access to URL query parameters for server-side processing, with Express.js offering a more JavaScript-native approach that integrates seamlessly with modern web development practices.
Conclusion
Accessing query string parameters in Express.js is straightforward through the req.query object, which automatically parses URL query strings into JavaScript objects. This approach provides significant advantages over PHP’s $_GET by maintaining proper data types and array structures, making it more intuitive for JavaScript developers.
Key takeaways include:
- Use
req.query.parameterNamefor basic parameter access - Express automatically handles arrays when parameters repeat (e.g.,
?color=red&color=blue) - Implement proper validation using libraries like express-validator for production applications
- Convert string parameters to appropriate types (numbers, booleans) as needed
- Handle optional parameters with default values using destructuring
For building robust APIs, always validate and sanitize query parameters before processing them, and consider implementing middleware for common patterns like pagination and filtering. The Express.js query parameter system provides the flexibility needed for modern web applications while maintaining simplicity for basic use cases.
Sources
- How to get GET (query string) variables in Express.js on Node.js - Stack Overflow
- Query Parameters in Express - Mastering JS
- Get Query Strings and Parameters in Express.js - Stack Abuse
- How do you access query parameters in an Express JS route handler? - GeeksforGeeks
- How to get query string params using Node and Express - Suraj Sharma
- Getting Query String Variables in Express.js - Tutorialspoint
- Reading Query Parameters in Node - GeeksforGeeks
- Query Parameter in Express - Scaler Topics
- How to handle query parameters in Node.js Express - APIDog
- Query parameters in Express - Stack Overflow