Skip to content

文字列をURLエンコード・デコードする snippet

文字列をパーセントエンコードして URL に安全に配置できるようにし、またデコードして戻します。古典的な落とし穴はスペースです。クエリ用のエンコードはプラス(フォーム方式)を生成し、パス用のエンコードは %20 を生成します。そのため PHP の urlencode と Java の URLEncoder は encodeURIComponent と一致しません。挿入する部品(1つのクエリ値、1つのパスセグメント)だけをエンコードし、URL 全体は決してエンコードしないでください。さもないと、URL に構造を与える & や ? の区切り文字を二重にエンコードしてしまいます。

文字列をパーセントエンコードして URL に安全に配置できるようにし、またデコードして戻します。古典的な落とし穴はスペースです。クエリ用のエンコードはプラス(フォーム方式)を生成し、パス用のエンコードは %20 を生成します。そのため PHP の urlencode と Java の URLEncoder は encodeURIComponent と一致しません。挿入する部品(1つのクエリ値、1つのパスセグメント)だけをエンコードし、URL 全体は決してエンコードしないでください。さもないと、URL に構造を与える & や ? の区切り文字を二重にエンコードしてしまいます。

Runnable recipe · 11 languagesurl-encode ツールを開く →
Crypto & Encodingurlpercent-encodingencoding

Every language

11 languages, copy-ready. One at a time with syntax highlighting, or all inline.

JSJavaScript
const encoded = encodeURIComponent('hello world & friends');
console.log(encoded); // hello%20world%20%26%20friends

const decoded = decodeURIComponent(encoded);
console.log(decoded); // hello world & friends

encodeURIComponent leaves A-Z a-z 0-9 - _ . ! ~ * ' ( ) intact. Its sibling encodeURI keeps URL structure (& = ? /) — usually the wrong tool for values.

TSTypeScript
const encode = (value: string): string => encodeURIComponent(value);
const decode = (value: string): string => decodeURIComponent(value);

console.log(encode('café & crème')); // caf%C3%A9%20%26%20cr%C3%A8me
console.log(decode(encode('café & crème')));

decodeURIComponent throws URIError on a stray % — wrap untrusted input in try/catch.

GoGo
package main

import (
	"fmt"
	"net/url"
)

func main() {
	encoded := url.QueryEscape("hello world & friends")
	fmt.Println(encoded) // hello+world+%26+friends

	decoded, _ := url.QueryUnescape(encoded)
	fmt.Println(decoded)
}

QueryEscape makes spaces + (query style); url.PathEscape makes them %20 for path segments. Both decode with their matching Unescape.

RsRust
use urlencoding::{decode, encode};

fn main() {
    let encoded = encode("hello world & friends");
    println!("{encoded}"); // hello%20world%20%26%20friends

    let decoded = decode(&encoded).unwrap();
    println!("{decoded}");
}

Two crates split the job: urlencoding is the drop-in (%20 style, encode/decode pair), percent-encoding is the builder — utf8_percent_encode(s, NON_ALPHANUMERIC) when you need a custom ASCII set, returning a Cow<str>. decode() is Result — a stray % is an Err, not a panic.

PHPPHP
<?php
$encoded = rawurlencode('hello world & friends');
echo $encoded, PHP_EOL; // hello%20world%20%26%20friends

echo rawurldecode($encoded), PHP_EOL;

rawurlencode matches %20 style. urlencode() is the form-encoding sibling that turns spaces into +.

PyPython
from urllib.parse import quote, unquote

encoded = quote('hello world & friends', safe='')
print(encoded)  # hello%20world%20%26%20friends

print(unquote(encoded))

quote's safe='' matters — by default '/' survives, which is wrong inside a query value. quote_plus() is the + style.

C#C#
var encoded = Uri.EscapeDataString("hello world & friends");
Console.WriteLine(encoded); // hello%20world%20%26%20friends

Console.WriteLine(Uri.UnescapeDataString(encoded));

EscapeDataString is for values. EscapeUriString (obsolete in .NET 6+) kept separators — do not use it.

JvJava
import java.net.URLEncoder;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;

public class EncodeDemo {
    public static void main(String[] args) {
        String encoded = URLEncoder.encode("hello world & friends", StandardCharsets.UTF_8);
        System.out.println(encoded); // hello+world+%26+friends

        System.out.println(URLDecoder.decode(encoded, StandardCharsets.UTF_8));
    }
}

URLEncoder is form-encoding: spaces become +. The pre-Java-10 overload without a charset used platform default — always pass UTF_8.

SwSwift
let queryStyle = "hello world & friends"
    .addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
// "hello%20world%20&%20friends" — space escaped, & KEPT (query-structural)

let aggressive = "hello world & friends"
    .addingPercentEncoding(withAllowedCharacters: .alphanumerics)
// "hello%20world%20%26%20friends"

let decoded = aggressive?.removingPercentEncoding

The CharacterSet choice decides the escaping set — .urlQueryAllowed keeps & = ? + (fine for a whole query, WRONG for one value containing &), .alphanumerics is the aggressive pick for single values. Both calls return String? because they can fail on invalid UTF-8.

KtKotlin
import java.net.URLDecoder
import java.net.URLEncoder

val encoded = URLEncoder.encode("hello world & friends", Charsets.UTF_8)
println(encoded) // hello+world+%26+friends

val decoded = URLDecoder.decode(encoded, Charsets.UTF_8)

URLEncoder is FORM encoding — spaces become +, the same + vs %20 caveat as the java impl (encodeURIComponent's %20 is the other style). Always pass Charsets.UTF_8 explicitly, never rely on a platform default.

RbRuby
require 'uri'

encoded = URI.encode_www_form_component('hello world & friends')
puts encoded # hello+world+%26+friends

puts URI.decode_www_form_component(encoded)

encode_www_form_component is + style (forms). ERB::Util.url_encode gives the %20 style; decode with URI.decode_uri_component.

Keep going

Try the interactive url-encode tool →