# 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:

```plaintext
/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:

```javascript
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:

```plaintext
/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`:

```javascript
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

```javascript
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

```javascript
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:

```javascript
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 posts
    
*   `GET /users/123/posts?sort=date` → User 123's posts sorted by date
    
*   `GET /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 `&`:

```javascript
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:**

```plaintext
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:

```javascript
app.get('/products', (req, res) => {
  const colors = req.query.color;
  res.json({ colors });
});
```

**Usage:**

```plaintext
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:

```javascript
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:

```javascript
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**

```javascript
// 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**

```javascript
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.params` and query strings via `req.query`
    
*   Combine 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.
