Express.js Handling Query Strings

Query strings are the most common way to send optional data to a server via a URL. You’ve likely seen them before in your browser’s address bar, appearing after a question mark (e.g., ?search=javascript&sort=newest). In Express.js, these key-value pairs are automatically parsed and made available to you through the req.query object, allowing you to build dynamic features like search engines, product filters, and pagination logic.

Developer Tip: Query strings are intended for data that "filters" or "modifies" the view of a resource. If you are identifying a specific resource (like a user ID), use URL Parameters (/users/:id) instead.

 

Key Features of Query Strings

  • Data Transmission: Query strings are primarily used with GET requests to pass data without changing the endpoint path.
  • Accessing Data: Express populates the req.query object with the parsed values, so ?user=john becomes { user: 'john' }.
  • Flexible Parameter Passing: You can append as many parameters as needed using the & separator.
Best Practice: Always provide default values for query parameters. Users might navigate to your route without providing any query strings, and your code should handle those cases gracefully to avoid errors.

 

Steps to Handle Query Strings in Express.js

Step 1: Set up a Basic Express Application
To get started, initialize your Node.js environment and install the Express framework:

npm init -y
npm install express --save

Step 2: Create an Express Application with Query String Handling
Create a file called app.js. In the example below, we will handle real-world scenarios such as a search bar, a product catalog filter, and a pagination system.

const express = require('express');
const app = express();

// 1. Basic Search Route
// Example: /search?q=nodejs
app.get('/search', (req, res) => {
    const searchTerm = req.query.q;
    
    if (!searchTerm) {
        return res.send('Please provide a search term using ?q=');
    }
    
    res.send(`Displaying results for: ${searchTerm}`);
});

// 2. Complex Filtering (Multiple Parameters)
// Example: /products?category=books&minPrice=10
app.get('/products', (req, res) => {
    const { category, minPrice } = req.query;
    
    // Applying defaults if parameters are missing
    const selectedCategory = category || 'All';
    const priceLimit = minPrice || 0;

    res.send(`Filtering products by Category: ${selectedCategory} and Minimum Price: $${priceLimit}`);
});

// 3. Pagination Logic
// Example: /posts?page=2&limit=5
app.get('/posts', (req, res) => {
    // Note: Query values are strings by default!
    const page = parseInt(req.query.page) || 1;
    const limit = parseInt(req.query.limit) || 10;

    res.json({
        message: "Fetching posts",
        currentPage: page,
        itemsPerPage: limit,
        skip: (page - 1) * limit
    });
});

// Start the server
app.listen(3000, () => {
    console.log('Server is running at http://localhost:3000');
});
Watch Out: All values in req.query are received as strings. If you expect a number (like a price or a page number), you must use parseInt() or Number() before doing calculations.

Step 3: Run the Application
Launch your server using Node.js:

node app.js

Step 4: Test the Routes
You can test these endpoints directly in your browser or through a tool like Postman. Notice how the URL changes based on the data you want to send:

  • http://localhost:3000/search?q=express – The server reads req.query.q as "express".
  • http://localhost:3000/products?category=electronics&minPrice=500 – This passes two keys: category and minPrice.
  • http://localhost:3000/posts?page=3&limit=20 – Useful for paginated APIs.
  • http://localhost:3000/posts – Uses the default values (Page 1, Limit 10) defined in our code.
Common Mistake: Forgetting that query strings are public and visible in the browser history. Never pass sensitive information like passwords or API keys through a query string.

 

Accessing Query String Parameters

The req.query object is the heart of query string handling in Express. It key-matches the names you provide in the URL. For example:

// URL: /settings?theme=dark¬ifications=true
const theme = req.query.theme;          // "dark"
const notify = req.query.notifications;  // "true" (as a string)

Handling Missing Query Parameters

Since you cannot control what a user types into the URL, your application must be resilient. Using the logical OR operator (||) or Destructuring with default values is the standard way to handle missing data:

// Using OR operator
const sortBy = req.query.sort || 'date';

// Using Object Destructuring with defaults
const { page = 1, limit = 10 } = req.query;
Best Practice: Use a validation library like joi or express-validator for complex applications. This ensures the query strings contain the correct data types and formats before your logic runs.

 

Summary

Handling query strings in Express.js is straightforward thanks to the built-in req.query object. By capturing these key-value pairs, you can create highly interactive routes that allow users to filter, sort, and paginate through data. Always remember to sanitize and validate these inputs, as query strings are easily manipulated by users, and always treat incoming data as strings until you convert them to the necessary types for your application.