Skip to main content

Bulk URL Encode / Decode

Encode or decode many URLs at once. Paste a newline-separated list and the tool processes each line in parallel, preserving order and blank lines.

Reviewed by · Last reviewed

How to use the bulk URL encoder and decoder

  1. Paste your list into the textarea. One URL or percent-encoded string per line; blank lines pass through unchanged so the input and output stay row-aligned.
  2. Pick the direction. Encode converts raw text into percent-encoded form. Decode reverses it.
  3. Toggle Full URL mode if your inputs are already complete URLs (with scheme, host, and path) and you only want the strictly unsafe characters escaped. Off, the tool runs encodeURIComponent; on, it runs encodeURI.
  4. Copy the output panel. Same line count as the input, same ordering, blank lines preserved at the same positions. Paste into a spreadsheet for a two-column reference, into a fixture file, or back into your migration script.

What the tool does under the hood

The component splits the input on \n and processes each line through the same encoding helpers used by the single-input URL Encode / Decode tool: either encodeURIComponent / decodeURIComponent (component mode, the strict default) or encodeURI / decodeURI (full URL mode). Both are part of the ECMAScript standard library and have been stable across all browsers since ES3. Lines that fail to decode (malformed percent sequences, bare %, or %XX where XX is not hex) emit an empty string and the first failing line is reported in the status panel; the rest of the batch continues, which is the least-surprise behavior for migration work.

The two encoding scopes differ on which characters they treat as reserved. encodeURIComponent escapes everything except the unreserved set defined by RFC 3986 (A-Z, a-z, 0-9, and - _ . ! ~ * ' ( )), so it is safe to drop into any URL position. encodeURI additionally leaves the URL-reserved punctuation (: / ? # [ ] @ ! $ & ' ( ) * + , ; =) untouched, which is what you want when the input is an already-formed URL and you only need to escape spaces and accents inside the path.

When this tool earns its keep

  • Migrating a list of URLs out of an old CMS where slugs included Unicode characters, and the new system needs them percent-encoded.
  • Cleaning up a CSV export of analytics data where every URL is double-encoded; running decode twice surfaces the original.
  • Preparing a fixture file for integration tests where each URL must round-trip through encoding without manual editing.
  • Cross-checking that a backend's URL encoding (Python urllib.parse.quote, Ruby CGI.escape, Java URLEncoder.encode) matches what the browser produces; small differences around + and %20 bite during integrations.
  • Decoding a column of error-tracking URLs from a Sentry or Datadog export to find which page actually failed.
  • Producing a sitemap-import fixture from a hand-edited URL list where some entries contain spaces or quotes.

Common pitfalls and edge cases

  • Spaces become %20, not +. The query-string convention of using + for space is older than RFC 3986 and only applies inside application/x-www-form-urlencoded bodies. encodeURIComponent always emits %20; if you need +, post-process with .replace(/%20/g, '+').
  • Plus signs in inputs are NOT decoded as spaces. decodeURIComponent("a+b") returns "a+b", not "a b". If your source emitted form-encoded data, switch to a form-aware decoder before piping through this tool.
  • Already-encoded inputs double-encode silently. encodeURIComponent("%20") returns "%2520", because the % itself is reserved. If your list might already be encoded, decode first and re-encode.
  • Component mode escapes too aggressively for full URLs. Encoding https://example.com/path in component mode produces https%3A%2F%2Fexample.com%2Fpath, which is rarely what you want. Toggle Full URL mode for already-formed URLs.
  • Unicode outside the BMP needs surrogate pair handling. encodeURIComponent emits the UTF-8 bytes of the four-byte sequence; old servers expecting WTF-8 or CESU-8 will misparse it. This bites with emoji and rare CJK characters.
  • Hard line limits. The tool runs synchronously, so 10K+ lines of long URLs may freeze the tab briefly. For larger batches, switch to a CLI.

Percent-encoding and RFC 3986

Percent-encoding (also called URL encoding) is defined by RFC 3986, the URI generic syntax. The rule is simple: any byte not in the unreserved set is replaced with %XX where XX is the uppercase hexadecimal of the byte value. Multi-byte characters are encoded as the UTF-8 byte sequence, then each byte is percent-encoded. The reserved set splits into two subsets: gen-delims (: / ? # [ ] @) and sub-delims (! $ & ' ( ) * + , ; =); the JavaScript encodeURI helper preserves both, while encodeURIComponent escapes them all. The split exists because reserved characters carry structural meaning in URL components, and escaping them inside a component is the only way to embed user data safely.

Alternatives and when they beat this tool

For very large batches, use a CLI: jq -R '@uri' on each line, or Python's urllib.parse.quote / unquote in a one-liner. AWK and sed both have URL-encode helpers as first-class snippets in their cookbooks. Inside Node, every file in your project already has access to the same encodeURIComponent the browser uses; a 5-line script handles batches without the main-thread blocking. The on-page bulk tool wins when you have a list in your clipboard, want a quick visual diff between input and output, and do not want to upload private URLs to a remote service like urlencoder.org.

Frequently Asked Questions

How does the bulk mode differ from the single-input page?

Same engine, batch input. Paste a newline-separated list of URLs (or percent-encoded strings) into the textarea and every line is processed independently. The output is the same number of lines, in the same order, so you can paste both columns into a spreadsheet for a side-by-side reference.

What happens if one line fails to decode?

That line shows as blank in the output and the panel reports the first offending line in the error band. The rest of the list still encodes / decodes - one bad line does not abort the batch. This is the least-surprise behaviour for bulk migration work.

Component or full URL mode?

Toggle "Full URL mode" to switch between <code>encodeURIComponent</code> and <code>encodeURI</code>. Component mode is the conservative choice for query-string values; full URL mode preserves <code>:</code>, <code>/</code>, <code>?</code>, <code>#</code> for already-formed URLs.

Is there a hard line limit?

The tool runs synchronously in the main thread, so very large pastes (10K+ lines of long URLs) may freeze the tab briefly. For batch sizes that big, fall back to a CLI like <code>jq -R</code> + <code>@uri</code> or a quick shell loop with <code>printf %s | python3 -c ...</code>.

Does the page upload my list anywhere?

No. The batch encoder is the same Preact component as the single-input one, just with <code>bulkMode</code> on. There is no fetch call or analytics beacon for the URLs you paste.

More Developer Tools