TidyURLs
Go to Tools
BLOG
The TidyURLsJournal

Practical guides, tutorials, and insights about URLs, SEO, web development, and online marketing. Learn, troubleshoot, and get the most of the web.

Back to the Journal
TidyURLs Journal

Why URL Fragments Aren’t Sent to the Server

Practical insights, clear explanations, and useful ideas for understanding the web.

October 28, 20266 min read5 topics
Why URL Fragments Aren’t Sent to the Server
Explore the details
#URLs#HTTP#Web Development#JavaScript#Client-Side Routing
October 28, 20266 min read

A URL such as https://example.test/article?mode=demo#section-2 contains information for both the server and the browser. The path and query can be included in the HTTP request; the fragment is handled by the browser and is not sent as part of that request. This distinction matters when you are reading server logs, building client-side navigation, or deciding where URL state belongs.

Key Takeaways

  • A URL fragment is the part after #. Browsers use it for navigation within a document and for client-side behavior.
  • The fragment is not included in the HTTP request target. A server handling /article?mode=demo#section-2 receives /article?mode=demo.
  • The query string, unlike the fragment, is sent in the request target and may appear in server logs.
  • A hash-based client-side router can read the fragment in the browser, but a server cannot route a request based on a fragment it never receives.

What the parts of a URL mean

Consider this URL:

https://example.test:443/articles?tag=web#anchors
PartExampleWhat it is used for
Originhttps://example.test:443Identifies the scheme, host, and port that define the web origin.
Path/articlesIdentifies a resource or route on the server.
Query?tag=webCarries parameters included in the HTTP request target.
Fragment#anchorsIdentifies a location or state for the browser to handle.

The fragment is separated from the rest of the URL by #. It is not part of the origin, path, or query. When a browser makes an HTTP request, it uses the URL without the fragment. The server therefore cannot use the fragment to choose which response to send.

The query and fragment can both look like client-side state, but they have different network behavior: query parameters are sent to the server; fragments are not sent in the HTTP request.

Reproduce it in a browser and server log

Save this small Node.js server as server.js:

const http = require("node:http");

const server = http.createServer((req, res) => {
  console.log(`${req.method} ${req.url}`);

  res.writeHead(200, { "content-type": "text/html; charset=utf-8" });
  res.end(`<!doctype html>
<html lang="en">
  <meta charset="utf-8">
  <title>Fragment test</title>
  <h1>Fragment test</h1>
  <p><a href="#section-2">Go to section 2</a></p>
  <div style="height: 100vh"></div>
  <h2 id="section-2">Section 2</h2>
</html>`);
});

server.listen(3000, () => {
  console.log("Listening at http://localhost:3000");
});

Run it with Node.js:

node server.js

Open http://localhost:3000/article?mode=demo#section-2 in a browser. The server log will show a request like:

GET /article?mode=demo

The path /article and query ?mode=demo are present. The fragment #section-2 is absent. The browser can still use it to scroll to the matching element in the returned document; the server does not need to receive it for that navigation to happen. If you click the in-page link, the browser can move to the target without making a new request for the document.

You can verify the same distinction in your browser’s Network panel: inspect the document request and compare its URL with the address bar. Do not use curl with a URL fragment as the sole demonstration; command-line URL clients may handle fragments locally too, so that does not show what a browser sends during navigation.

Where fragments are useful

In-page anchors

A link such as <a href="#section-2"> points to an element whose id is section-2. Browsers use this pattern for table-of-contents links and direct links to sections. The fragment can also be used by browser features and web applications for other fragment-based behaviors; it is not limited to ordinary element IDs.

Hash-based client-side routing

Some single-page applications put route state in the fragment, for example https://example.test/#/settings. Client-side JavaScript can read location.hash and update the displayed view. Because the fragment is not sent in the request, the server sees the same path and query whether the browser address ends in #/settings or #/profile.

That can make hash-based routes convenient when the server is not configured to serve application routes directly. It also means server logs alone cannot tell which hash route a user viewed. If you need server-side routing, authorization, or logging for a route, use a path or query parameter and configure the server to handle it. With History API routing, for example, direct navigation or a page refresh still sends the route path to the server, so the server may need to return the application entry point for those routes.

State that belongs only in the browser

Fragments can be suitable for browser-side navigation or state that does not need to be part of the server request. They are not automatically private: users can see them in the address bar, copy them, and browser-side scripts can read them. Do not treat a fragment as a secure storage location for secrets.

When the distinction matters

If an application expects the server to receive a fragment, that design will fail: the server cannot inspect information that the browser leaves out of the request. Check the URL in the address bar, then compare it with the request target in the Network panel or server logs.

If the server needs a value to return a different response, include it in the path or query instead. Remember that query values are sent with requests and can be recorded in logs and other infrastructure. Choose the URL component based on which side needs the information, not just on which syntax looks convenient.

Common Mistakes

  • Looking for #fragment in server access logs. The fragment is not part of the HTTP request target, so the absence is expected.
  • Treating a query parameter like a fragment. ?tab=details is sent in the request; #details is not.
  • Assuming a fragment change always reloads the page. In-page fragment navigation can happen within the current document without a new document request.
  • Using a fragment for server-side authorization or routing. The server never receives it, so it cannot enforce decisions based on it.
  • Assuming fragments are secret because they are not sent to the server. They remain visible and available to browser-side code.

Best Practices

  • Use fragments for in-document navigation and client-side behavior that the server does not need to process.
  • Use a path or query parameter when the server must receive a value, and handle sensitive values carefully because requests may be logged.
  • For single-page applications, decide whether routes belong in the fragment or path. Account for direct links, refreshes, server fallbacks, and the logging needs of your application.
  • When debugging, compare the address bar with the actual document request rather than assuming every visible URL character reaches the server.

Conclusion

The browser uses a URL fragment after #, but leaves it out of the HTTP request. That is why anchors and hash-based routes can work in the browser while remaining invisible in server logs. Put information in the path or query when the server needs to receive it, and use fragments for browser-side navigation and state.

References

Documentation note: Live source retrieval was not available while preparing this article; the links above are provided as relevant references, but their current contents were not checked in this session.