innovhelix.
Encoding & URLs · Troubleshooting

Find and fix double URL encoding without decoding blindly

Unwanted extra layer: %20 and %2520 illustrated for diagnose repeated percent encoding.

An expected %20 sometimes becomes %2520 because the percent sign was encoded a second time. One decode then returns an encoded representation instead of the original value. That indicates an extra layer only when the format expected one layer. Nested URLs and literal percent signs can legitimately produce similar text.

Try the URL Encoder & Decoder with the synthetic example below. Processing stays in your browser; the guide explains what the result can and cannot establish.

Worked example: unwanted extra layer

Use this exact sample to isolate the behavior discussed above. Keep the operation and options with the sample when reporting a result; changing the input representation can change what the test demonstrates.

Input or question

Raw: hello world
Once: hello%20world
Twice: hello%2520world

Expected result or interpretation

Expected decoded application value: hello world

Literal percent-looking search text is legitimate

A user searching documentation for the characters %20 means a percent sign followed by two digits, not necessarily a space. Encode that raw search value once and the component contains %2520. After the intended one decode, the receiver should recover %20. A decode-until-stable loop would change it into a space and corrupt the search. This is why %25 is evidence to investigate rather than an automatic error marker. Add the fixture beside a true double-encoding failure involving a raw space. The two cases can produce similar intermediate strings but have different intended receiver values. The correct fix depends on the original value and its encoding boundary.

Follow the transformation chain

hello world becomes hello%20world after component encoding and hello%2520world after another pass. One decode of the second representation returns hello%20world. This demonstrates the layering but does not prove every %25 is a bug. A literal percent in the original value should be encoded too. Keep the raw input available so diagnosis is based on the intended data rather than the output’s appearance.

Assign one owner per boundary

A query builder that encodes raw values should not receive manually pre-encoded values. Likewise, a backend query parser may already decode the value before your handler sees it. Document whether a function accepts raw text, an encoded component or a complete URL. Ambiguous argument contracts encourage duplicate conversions during refactoring. A boundary-level integration test is more useful than a generic replace operation.

Avoid decode-until-stable loops

Repeated decoding can reveal delimiters that an earlier validator did not inspect and can damage legitimate percent-looking text. Apply the transformations defined by the format, then validate in the destination context. A debugging shortcut should not become a production normalization policy. Preserve an error when the structure is malformed instead of silently accepting an arbitrary number of escaping layers.

Nested URLs require structural reasoning

A redirect target passed as one query value contains its own separators and percent escapes. The outer query must encode that target as data. Decode the outer component once to recover the inner URL, then parse the inner URL according to its own structure. Extra %25 sequences can therefore be intentional. Test raw percent, spaces and nested targets separately to distinguish this case from a double-encoding defect.

Name intermediate representations explicitly

Variables called value, encodedValue and requestUrl make conversion ownership easier to inspect than several variables all called url. Better still, use a query builder whose interface accepts raw values and avoid retaining encoded components longer than necessary. A function receiving an encoded component should say so in its contract. A function receiving a complete URL should not apply the same assumptions as one receiving a single value.

Add fixtures for a literal percent, a percent-looking string and a nested target. These prevent an overaggressive fix that decodes every %25 sequence once more. For example, a user may legitimately search for the text %20 rather than a space. The intended receiver value is that literal text. A nested redirect target may also contain an encoded component that must survive outer parsing. Analyze the number of layers from the structure and protocol, not from whether the output contains doubled percent escapes. In a production input pipeline, validation should apply to the form that the destination actually uses. If one layer validates before another unexpected decode, delimiters can acquire a new meaning later. Keeping conversion ownership explicit makes that risk easier to reason about and prevents debugging shortcuts from becoming accepted parsing rules.

Verification cases

  • Search text %20: Can legitimately require %2520 in one encoded component.
  • Space encoded twice unintentionally: Remove the redundant boundary conversion.
  • Nested URL with its own escapes: Respect outer and inner layers separately.

Decision reference

CaseMeaning or choiceWhat to do with it
%20Space escapeNormal component output
%2520Encoded percent plus 20May indicate an extra layer
100%25Encoded literal percentCan be correct
Nested target URLOuter component encodingDecode by structure

Before you use the result

  1. Document raw vs encoded arguments.
  2. Let one builder own query encoding.
  3. Avoid unrestricted repeated decoding.
  4. Include literal-percent and nested-URL tests.

Continue the workflow

encodeURI vs encodeURIComponent: encode the right boundary addresses encode query values without breaking urls. Why a plus sign becomes a space in a query string addresses debug plus signs in query/form data.

Technical reference

Consult MDN browser API reference for the relevant underlying behavior or concept. Test the exact runtime used by your application when engine compatibility matters.

Corrections are welcome through Contact & feedback. Read our editorial policy for scope and limitations.