Two API request URLs can look almost identical but produce different results—or look different while conveying the same query values. Comparing them component by component helps you find changes in the host, path, query, and fragment without assuming what the API will do with them.
Key Takeaways
- Compare URL components separately: scheme, host, path, query, and fragment.
- Query parameter order may be irrelevant to an API, but repeated keys, request-signing rules, or infrastructure can make order matter.
- Trailing slashes and encoded characters can change a path or its interpretation.
- A URL comparison identifies differences; it does not tell you whether the API accepts or correctly interprets either URL.
Compare URL Components, Not Just Strings
Start by separating the URLs into parts. For example:
https://api.example.test/v1/items?tag=red&limit=10
https://api.example.test/v1/items/?limit=10&tag=red#debug
The scheme, host, and query values are the same, but the second URL has a trailing slash in its path and a fragment. Those differences may matter to a client, a router, or other processing around the request.
A component-by-component comparison is easier to diagnose than a whole-string comparison:
| Component | What to check |
|---|---|
| Scheme | http versus https |
| Host | Hostname and port, such as api.example.test:8443 |
| Path | Each path segment, including a trailing slash and encoded characters |
| Query | Parameter names, values, repeated keys, and order |
| Fragment | Text after #; normally not sent in an HTTP request to the server |
A fragment can still affect client-side behavior, such as which page state a browser displays. But in a normal HTTP request, the fragment is not part of the request sent to the server. If you are diagnosing what the API received, inspect the actual request in your client or network logs rather than relying on the full URL copied from a browser address bar.
Use JavaScript to Compare Two URLs
The built-in URL and URLSearchParams APIs can show parsed components and query pairs. This Node.js example reports both the query as written and the parsed query pairs. Replace the two example URLs with the ones you are investigating.
const first = new URL(
"https://api.example.test/v1/items?tag=red&tag=blue&limit=10"
);
const second = new URL(
"https://api.example.test/v1/items/?limit=10&tag=blue&tag=red#debug"
);
const entries = (url) => [...url.searchParams.entries()];
const sortedPairs = (pairs) =>
pairs.map((pair) => JSON.stringify(pair)).sort();
const firstEntries = entries(first);
const secondEntries = entries(second);
const report = {
protocol: [first.protocol, second.protocol],
host: [first.host, second.host],
pathname: [first.pathname, second.pathname],
query: {
raw: [first.search, second.search],
rawChanged: first.search !== second.search,
orderedPairs: [firstEntries, secondEntries],
orderedPairsChanged:
JSON.stringify(firstEntries) !== JSON.stringify(secondEntries),
pairMultisetChanged:
JSON.stringify(sortedPairs(firstEntries)) !==
JSON.stringify(sortedPairs(secondEntries)),
},
fragment: [first.hash, second.hash],
};
console.log(JSON.stringify(report, null, 2));
In this example, the paths differ because only the second has a trailing slash. The raw queries and ordered pairs differ. The parsed pair collections are the same when sorted, so the query contains the same name-value pairs despite their changed order. The fragment differs too.
This is a diagnostic comparison, not a complete byte-for-byte URL inspection. Parsing can normalize parts of a URL, and URLSearchParams decodes query names and values. Keep the original URL strings if you need to investigate the exact spelling or encoding sent by a client.
Decide Whether Query Order Matters
For many APIs, query parameters are treated like an unordered set of name-value pairs. Under that assumption, these may mean the same thing:
?limit=10&sort=name
?sort=name&limit=10
But do not assume every system treats them that way. Order can matter when:
- A parameter appears more than once, as in
?tag=red&tag=blue. An API might preserve the order, treat the values as a list, or handle duplicates in another way. - A request signature is calculated from the query string. The client and server must follow the same signing and canonicalization rules.
- A cache, proxy, router, or other intermediary uses the query string as part of its key or matching logic.
- An application processes parameters in order or chooses one occurrence of a repeated key.
Compare both the raw query and the parsed name-value pairs. If only the raw query changes, inspect whether the difference is parameter order or encoding before concluding that the request's meaning changed.
Check Trailing Slashes and Encoded Characters
A trailing slash is part of the path: /v1/items and /v1/items/ are different path strings. An API gateway or server might route them to the same handler, redirect one, or treat them as separate routes. The comparison reveals the difference; the service's behavior determines its effect.
Encoded characters also deserve a close look. For example, %2F represents an encoded slash, while / is a literal path separator. A client, router, or server may handle those forms differently. In a query, + is commonly decoded as a space by form-style query parsing, while %2B represents a literal plus sign. Compare the original query text as well as the parsed values when encoding could explain a mismatch.
Do not assume visually similar encodings are interchangeable. Check what the client actually sends and how the API documents and parses the relevant path or parameter.
A Practical Troubleshooting Workflow
- Copy both complete URLs from the same point in the request flow, such as the client configuration or network inspector.
- Compare the scheme, host, and port. Confirm the request is going to the intended environment.
- Compare paths character by character, including trailing slashes and percent-encoded segments.
- Compare query names and values, including repeated keys. Check both their order and exact encoded spelling.
- Note any fragment, but remember it normally is not sent to the API server in an HTTP request.
- Reproduce each request with the same method, headers, body, authentication, and client settings. A URL-only comparison does not capture those other inputs.
- Compare the API responses or server-side observations, and consult the API's routing and parameter rules to determine what the difference means.
A URL parser or diff view can help identify changed components, but it cannot establish whether a server accepts a URL or interprets it as intended.
Common Mistakes
- Treating every query-order change as meaningful. Some APIs ignore order; others do not. Check the API's behavior, especially for signed requests and repeated keys.
- Treating every query-order change as harmless. A list represented by repeated keys may have meaningful order, and intermediaries may use the raw query string.
- Overlooking duplicate keys.
?id=1&id=2is not necessarily equivalent to?id=2. - Ignoring the trailing slash. It changes the path string even if a particular server redirects or normalizes it.
- Comparing only decoded values. Parsing can hide differences in how characters were encoded.
- Assuming the fragment reached the API. A normal HTTP request does not send the fragment to the server.
- Assuming a URL diff explains the API response. Method, headers, body, authentication, routing, and server-side parsing can also affect the result.
Best Practices
- Save the original URL strings before parsing or normalizing them.
- Compare parsed components for diagnosis, then inspect the actual outgoing request when exact wire behavior matters.
- Preserve repeated query parameters in comparisons; do not reduce them to a simple key-value object that discards duplicates.
- Follow the API's documented rules for parameter order, encoding, paths, and signatures.
- Reproduce requests with other inputs held constant before attributing a response change to the URL.
Conclusion
To compare two URLs effectively, inspect their scheme, host, path, query, and fragment separately. Pay special attention to repeated parameters, order, trailing slashes, and encoding. The comparison tells you what changed; only the API's documented rules and observed request behavior tell you what that change means.
References
No external references were consulted for this article.
