# querry-cleaner: Express Middleware to Fix Duplicate Query Parameters
- **URL:** https://harshcodez.com/hots/querry-cleaner
- **Markdown URL:** https://harshcodez.com/hots/querry-cleaner.md
- **JSON URL:** https://harshcodez.com/hots/querry-cleaner.json
- **Author:** Harshcodez
- **Published Date:** 2026-07-24
- **Reading Time:** 2 min read
- **Tags:** express, nodejs, npm, middleware, open-source, typescript

> Duplicate query params cause silent bugs. querry-cleaner is a lightweight Express middleware that deduplicates them in one line — zero config, zero dependencies.

# Querry-Cleaner — Fixing Duplicate Query Parameters in Express

Duplicate query parameters are a real problem. A request like `/search?page=1&sort=name&page=2` can cause inconsistent behavior — some frameworks return the first value, some return the last, and some return an array where your code expects a string.

This is known as **HTTP Parameter Pollution**, and it's both a bug source and a security concern.

**querry-cleaner** is a zero-dependency Express middleware that deduplicates query parameters before they reach your route handlers.

## Install

```bash
npm install querry-cleaner
```

## Usage

```typescript
import express from "express";
import queryCleaner from "querry-cleaner";

const app = express();
app.use(queryCleaner());

app.get("/search", (req, res) => {
  // req.url is already clean — no duplicate keys
  res.json({ query: req.query });
});

app.listen(3000);
```

That's it. One line to add, zero config needed.

### Before & After

| Incoming request | What your handler sees |
|---|---|
| `/search?page=1&sort=name&page=2` | `/search?page=2&sort=name` |
| `/api?token=abc&token=xyz` | `/api?token=xyz` |

The last value wins — consistent, predictable behavior.

## Whitelist

Need certain routes to stay untouched? Pass a whitelist:

```typescript
app.use(
  queryCleaner({
    whitelist: ["/webhooks/stripe", "/health"],
  })
);
```

Whitelisted paths skip cleaning entirely.

## How It Works

The core logic is ~15 lines. It uses the built-in `URL` and `URLSearchParams` APIs — no external dependencies.

```typescript
const parsedUrl = new URL(req.url, "http://localhost");
const cleanParams = new URLSearchParams();

parsedUrl.searchParams.forEach((value, key) => {
  cleanParams.set(key, value); // .set() overwrites, .append() would keep both
});

req.url = parsedUrl.pathname + "?" + cleanParams.toString();
```

The trick is `.set()` vs `.append()` — calling `.set()` on an existing key overwrites it, so only the last value survives. The middleware rebuilds `req.url` with the cleaned params before calling `next()`.

## Links

- **npm**: [querry-cleaner](https://www.npmjs.com/package/querry-cleaner)
- **GitHub**: [harshcodezzz/querry-cleaner](https://github.com/harshcodezzz/querry-cleaner)
- **License**: [MIT](https://raw.githubusercontent.com/harshcodezzz/querry-cleaner/refs/heads/main/LICENSE)



