Regex Routing

When You Need More Than Simple Patterns

Regex Routing

Express accepts strings, parameterized patterns, and raw regex. Regex is overkill for most cases — but useful for some.

3 min read Level 2/5 #express#routing#regex
What you'll learn
  • Constrain params with regex
  • Use raw regex as a path
  • Know when to step back

app.get accepts a few path types:

  • A literal string: /users
  • A parameterized string: /users/:id
  • A parameterized string with a regex constraint: /users/:id(\\d+)
  • A raw RegExp: /^\/users\/\d+$/

Constraining a Parameter

Limit :id to digits only:

app.get("/users/:id(\\d+)", (req, res) => {
  res.json({ id: Number(req.params.id) });
});

GET /users/42 matches. GET /users/me doesn’t (falls through to the next route or 404).

A common alphanumeric ID pattern (UUIDs, e.g.):

const UUID_RE = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";

app.get(`/users/:id(${UUID_RE})`, getUser);

Now only UUID-shaped IDs match.

Raw Regex

For routes that defy normal patterns:

app.get(/^\/legacy\/(\d{4})\/(\d{2})$/, (req, res) => {
  const [year, month] = req.params;   // numeric indices
  res.json({ year, month });
});

With raw regex, captures land on req.params[0], req.params[1], etc. — numeric, not named.

When To Use It

  • API versioning: /api/v(\\d+)/users to constrain to digits
  • File extensions: /files/:name(.+).(jpg|png) (though static middleware is usually better)
  • Migration: matching legacy URL formats during a rewrite

When NOT To

Most of the time, named params and explicit routes are clearer:

// regex — clever but cryptic
app.get(/^\/posts\/(\d+)$/, getPostById);

// explicit — boring but obvious
app.get("/posts/:id(\\d+)", getPostById);

If someone reads your route file and has to consult regex docs, you’ve added a hurdle.

Escape Carefully

In a string regex constraint, you escape with \\. In a real RegExp, you use \. Easy to mix up.

404 Handlers →