New to Rust? Grab our free Rust for Beginners eBook Get it free →
Getting the Full URL in Express on Node.js: A Step-by-Step Guide

A route handler that builds a link or redirect can need the full address the visitor requested, including the host and the query string. Express doesn’t hand you that as one value, so you build it from properties like req.protocol and req.originalUrl.
I’ll build a route that returns the full URL and show what changes when your app runs behind a proxy.
What Is a Full URL in Express?
An absolute URL has a scheme and a host, followed by the request path and query string. Express keeps those values on separate request properties, as described in the Express 5 Request API, which you join when a handler needs one string.
In Express 5, req.protocol provides the scheme, req.host provides the host and port, and req.originalUrl preserves the original path with its query string.
| URL part | Express property | Example |
|---|---|---|
| Scheme | req.protocol | http |
| Host and port | req.host | localhost:3102 |
| Path and query | req.originalUrl | /products?category=books |
What You Need Before Running the Example
Express 5 requires Node.js 18 or newer. The example uses CommonJS, so save the route as app.js inside a Node.js project.
| Requirement | What to have |
|---|---|
| Node.js | Version 18 or newer for Express 5 |
| Project directory | A place to install Express and save app.js |
npm install express
This installs Express into the project where you will run the server. The sample below ran with Node.js 26.10.0 and Express 5.2.1.
Build the Express Route
A single route shows how the request properties work together. It returns the assembled URL as plain text, which keeps the response focused on the value.
Step 1: Create the Route
Use req.host for the host and port, then append req.originalUrl so the path and query stay together. The response uses text/plain rather than treating the returned URL as HTML.
const express = require('express');
const app = express();
const port = Number(process.env.PORT || 3102);
app.get('/products', (req, res) => {
const fullUrl = `${req.protocol}://${req.host}${req.originalUrl}`;
res.type('text/plain').send(fullUrl);
});
app.listen(port, () => {
console.log(`Listening on port ${port}`);
});
The path in app.get matches /products, while req.originalUrl also keeps the query string. That distinction matters when the handler needs the exact URL target rather than only the route name.
Step 2: Start the Server
Run the app from the project directory and leave the process active while you send a request from another terminal.
node app.js
Check the Returned Path and Query String
Send a request with a query parameter and compare the response with the address you called.
curl -sS 'http://localhost:3102/products?category=books'

I sent the request shown above. Express returned http://localhost:3102/products?category=books, with the query attached to the original path.
Handle Proxies and Untrusted Hosts
Without trust proxy, req.protocol describes the direct connection and req.host uses the Host header. When you configure proxy trust, Express 5 can take those values from X-Forwarded-Proto and X-Forwarded-Host.
- req.get(‘host’) reads the Host header directly. In Express 5, req.host can use X-Forwarded-Host when the proxy trust setting allows it.
- Configure trust proxy to match the actual proxy addresses or hop count. Do not enable it blindly.
- The last trusted proxy must overwrite forwarded headers supplied by a client, or the application can accept spoofed protocol and host values.
I set Host to attacker.example, and I saw the route echo it in plain text. The screenshot shows why a request-derived host is not proof of your public domain.

Express’s proxy guide explains trust proxy. Match it to the actual network path and have the last trusted proxy overwrite forwarded headers supplied by clients.
Use a Configured Origin for Trusted Links
A URL reconstructed from a request describes that request, not your application’s public identity. For password-reset links and redirects, build from a configured public origin and validate any user-provided destination against allowed hosts.
PUBLIC_ORIGIN=https://app.example.com node -e "console.log(new URL('/reset', process.env.PUBLIC_ORIGIN).href)"
With PUBLIC_ORIGIN set to https://app.example.com, the command prints https://app.example.com/reset. The host comes from configuration.
Express’s security guidance explains why redirect destinations need validation.
Express Full URL Questions
The request properties answer the common path and proxy questions directly.
Does req.originalUrl include the query string?
Yes. Express documents req.originalUrl as the original request URL, including the path and query string.
Does req.host include a port?
Yes. Express 5 documents req.host with the port when the Host header includes one, such as example.com:3000.
Why does req.protocol show http behind a proxy?
Express uses X-Forwarded-Proto when trust proxy is configured. Set that option to match the proxy chain and ensure the trusted proxy overwrites forwarded headers.




