파일 업로드
  1. base64hub
  2. 웹·토큰 도구
  3. URL 디코딩

URL 디코더 (퍼센트 디코딩)

인코딩된 URL, 쿼리 문자열, 로그 줄을 붙여넣으면 %20, %2F, %C3%A9를 다시 텍스트로 바꿉니다. 전체 URL은 호스트, 경로, 디코딩된 쿼리 파라미터로 나눠서도 보여 줍니다.

무료 가입 없음, 제한 없음 로컬 업로드 없음 반복 디코딩 이중·삼중 인코딩을 최대 5회까지 풀기 업데이트 2026. 10. 27.
입력 0출력 0

브라우저에서 처리됩니다. 이 페이지는 데이터를 어디로도 보낼 수 없습니다 – 확인 방법

URL을 디코딩하는 방법

  1. 인코딩된 텍스트를 인코딩된 URL 또는 텍스트에 붙여넣으세요.
  2. 쿼리 문자열과 폼 데이터에는 +를 공백으로 처리를 켜 두고, 경로나 Base64 값에는 끄세요.
  3. 결과에 아직 %XX 시퀀스가 남아 있으면 상태 메시지가 알려 줍니다. 반복 디코딩을 켜세요.
  4. 로그 파일이나 값이 한 열로 나열된 목록이라면 줄마다 따로를 켜서 줄마다 따로 디코딩하세요.
  5. 원본이 UTF-8이 아니면 문자 인코딩을 고른 뒤 출력 복사를 누르세요.

입력이 전체 URL이면 창 아래 표에 스킴, 호스트, 디코딩된 경로, 쿼리 파라미터(한 행에 하나씩), 프래그먼트가 표시됩니다. 길고 복잡한 추적 URL이나 리디렉션 URL을 읽는 가장 빠른 방법입니다.

예시

인코딩됨디코딩 결과참고
q=base64%20%26%20%22url-safe%22q=base64 & "url-safe"%26은 &, %22는 "
lang=%E6%97%A5%E6%9C%AC%E8%AA%9Elang=日本語UTF-8에서 문자당 3바이트
%F0%9F%98%80😀이모지는 4바이트
q=a+b%2Bcq=a b+c+를 공백으로 처리 사용 시
next=%252Fhome%253Ftab%253D1next=/home?tab=1이중 인코딩, 2회 디코딩
caf%E9caféUTF-8이 아니라 Windows-1252 또는 ISO-8859-1

이중 인코딩

이미 인코딩된 문자열을 다시 인코딩할 때마다 모든 %가 %25가 됩니다. 그래서 /는 %2F, 그다음 %252F, 그다음 %25252F가 됩니다. 리디렉션 URL이 여러 서비스를 거치거나, 코드에서 이미 인코딩한 값을 프레임워크가 또 인코딩할 때 생깁니다.

이런 문자열을 읽으려면 이스케이프가 남지 않을 때까지 디코딩하세요. 반복 디코딩이 그 일을 하고 횟수를 알려 줍니다. 원인을 고치려면 두 번째로 인코딩하는 계층을 찾으세요. 다른 URL을 담은 next=나 url= 파라미터처럼 정당하게 중첩된 URL은 정확히 한 겹만 더 인코딩되어야 합니다.

이메일 보안 게이트웨이는 이런 중첩이 흔히 생기는 곳입니다. Microsoft Defender Safe Links URL은 https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fexample.com%2Freset%3Fid%3D42&data=…처럼 생겼습니다. 붙여넣으면 아무것도 클릭하지 않고도 파라미터 표에서 실제 목적지 https://example.com/reset?id=42를 확인할 수 있습니다.

잘못된 이스케이프와 레거시 문자 인코딩

% 뒤에는 정확히 hex 두 자리가 와야 합니다. 100%, %zz, 이스케이프 중간에서 잘린 URL은 오류이며, 디코더는 N 위치의 이스케이프가 잘못되었습니다라고 알려 줍니다. JavaScript의 decodeURIComponent는 같은 경우에 URIError: URI malformed를 던지고, Python의 unquote는 시퀀스를 그대로 둡니다.

또 다른 오류 원인은 문자 인코딩입니다. 퍼센트 이스케이프는 바이트이고, %E9 하나만으로는 올바른 UTF-8이 아닙니다. Python은 이를 대체 문자로 디코딩하고 JavaScript는 오류를 던집니다. 문자 인코딩을 Windows-1252나 ISO-8859-1로 설정하면 é로 디코딩됩니다. Shift_JIS, GBK, EUC-KR, KOI8-R 등 다른 레거시 문자 인코딩도 같은 목록에 있습니다. 오래된 한국어 사이트의 URL에서 한글이 깨진다면 EUC-KR을 선택해 보세요.

코드에서 URL 디코딩

decodeURIComponent("a%20b%26c")                   // "a b&c"
new URLSearchParams("q=a+b%2Bc").get("q")          // "a b+c"
from urllib.parse import unquote, unquote_plus, parse_qs
unquote("caf%C3%A9")                     # 'café'
unquote("caf%E9", encoding="latin-1")    # 'café'
unquote_plus("q=a+b%2Bc")                # 'q=a b+c'
parse_qs("q=a+b%2Bc&tag=x&tag=y")        # {'q': ['a b+c'], 'tag': ['x', 'y']}

decodeURIComponent는 +를 공백으로 바꾸지 않지만, URLSearchParams와 unquote_plus는 바꿉니다. 문자열을 만든 방식에 맞는 것을 고르세요. 인코딩은 URL 인코더를, URL을 거쳐 온 Base64는 Base64URL 디코더를 참고하세요.

자주 묻는 질문

URL 인코딩된 문자열은 어떻게 디코딩하나요?

위에 붙여넣으면 입력하는 대로 디코딩된 텍스트가 나타납니다. JavaScript에서는 decodeURIComponent(s), Python에서는 urllib.parse.unquote(s)를 쓰고, +가 공백을 뜻한다면 unquote_plus(s)를 쓰세요.

디코딩한 URL에 아직 %20이나 %3A가 남아 있는 이유는 무엇인가요?

두 번 인코딩되었기 때문입니다. 한 번 디코딩하면 %2520이 %20이 되고, 두 번째에 공백이 됩니다. 반복 디코딩을 켜면 이스케이프가 남지 않을 때까지 최대 다섯 번 디코딩하고 몇 번 걸렸는지 알려 줍니다.

decodeURIComponent가 URI malformed 오류를 내는 이유는 무엇인가요?

100%처럼 % 뒤에 hex 두 자리가 없거나, Windows-1252 시스템에서 온 %E9처럼 바이트가 올바른 UTF-8이 아닌 경우입니다. 이 디코더는 정확한 위치를 알려 주며, 문자 인코딩 옵션으로 레거시 인코딩도 디코딩합니다.

+를 공백으로 디코딩해야 하나요?

쿼리 문자열과 폼 본문에서는 그렇습니다. 그래서 +를 공백으로 처리가 기본으로 켜져 있습니다. URL 경로나 Base64가 들어 있을 수 있는 값에서는 끄세요. 그런 곳의 +는 문자 그대로의 더하기 기호입니다.