ForHosting KIT · Developer Utilities

RFC 3986 percent encoder & decoder

Under strict RFC 3986, hello world!'()* becomes hello%20world%21%27%28%29%2A: only letters, digits, hyphen, period, underscore and tilde stay as they are. Decoding stops at a broken percent sequence instead of guessing. Free in your browser.

  • Free
  • Runs in your browser
  • No sign-up
  • Your data stays on your device
Use it from WebAPIEmailTelegramApp soon
If you enter
Text
hello world!'()*
Calculation mode
Encode
You get
Result
hello%20world%21%27%28%29%2A
Length
28
Standard
RFC 3986
Unreserved
A-Z a-z 0-9 - . _ ~

RFC 3986 defines the modern URI grammar and the exact unreserved character set that may appear without percent-encoding: letters, digits, hyphen, period, underscore, and tilde.

How RFC 3986 percent-encoding differs from encodeURIComponent

Percent-encoding replaces disallowed octets with a percent sign and two hexadecimal digits so a string can travel safely inside a URI component. RFC 3986 section 2.3 names the unreserved set—ALPHA, DIGIT, hyphen, period, underscore, and tilde—and states that these characters should not be percent-encoded when data is produced. Every other octet, including reserved gen-delims and sub-delims and all non-ASCII UTF-8 bytes, should be encoded when the value is treated as opaque data.

JavaScript’s encodeURIComponent uses a looser unescaped set that also keeps exclamation, apostrophe, open and close parenthesis, and asterisk as literal characters. That choice matches historical browser form behavior but diverges from strict RFC 3986 component encoding and from many server libraries written in Python, Go, Java, or Rust that only leave the six unreserved marks alone. The practical failure mode is subtle: a signature or cache key built from “hello!

world” may hash differently if one side emits hello! world and the other emits hello%21world. This tool always applies the RFC map on encode, producing uppercase hex (%21 not %21 mixed case preference), so multi-byte characters such as café become caf%C3%A9 and a space becomes %20, while !

' ( ) * become %21 %27 %28 %29 %2A. Decode accepts upper or lower hex digits, validates that every percent is followed by exactly two hex digits, then reconstructs UTF-8 text.

Where strict RFC 3986 encoding shows up in real work

Backend services that build signed redirect URLs, OAuth 1.0 parameter strings, or HMAC canonical requests often require percent-encoding that matches RFC 3986 rather than browser encodeURIComponent, because signature base strings treat ! ' ( ) * as characters that must be escaped. Mobile and desktop clients written outside the JavaScript ecosystem typically ship libraries that already follow the unreserved-only rule; a Node middleware that used encodeURIComponent for the same values would produce intermittent signature failures that only appear when a product title or display name contains an apostrophe or parenthesis.

Support engineers paste half-encoded strings from tickets and logs and need a decode path that fails loudly on truncated escapes instead of inventing characters. Curriculum authors teaching web foundations want a dedicated page for RFC 3986 percent-encoding with the explicit unreserved set rather than burying the topic under a generic URL encoder or Base64 tool, because search intent and the !'() * difference are what students and integrators look for.

Localization engineers verify that multi-byte languages round-trip through encode and decode without mojibake. If you need encodeURIComponent semantics, full-URI light encoding that preserves structural delimiters, Base64, or slug generation, treat those as separate search intents and landings rather than overloading this RFC 3986 encoder page.

OAuth and signed query strings

Percent-encode parameter values with the strict RFC 3986 unreserved set so HMAC and OAuth base strings match non-JavaScript peers that escape ! ' ( ) *.

Decode logged or pasted URI fragments

Decode percent-encoded fragments from logs and tickets back to readable UTF-8, with hard failures on incomplete or non-hex percent sequences.

How is this different from encodeURIComponent?

encodeURIComponent leaves ! ' ( ) * unescaped. This tool follows RFC 3986 unreserved characters only (A–Z a–z 0–9 - . _ ~) and percent-encodes those four sub-delims as %21 %27 %28 %29 %2A.

Can I both encode and decode?

Yes. Set mode to encode (default) to percent-escape plain text under RFC 3986 rules, or mode to decode to recover UTF-8 text from a percent-encoded string.

Are hex digits upper or lower case on encode?

Encode emits uppercase hexadecimal digits (%2A not %2a), which matches the preferred form in RFC 3986. Decode accepts both upper and lower hex.

What does the RFC 3986 percent encoder cost?

The browser tool is free and runs locally.

Why does my OAuth signature fail when a name has an apostrophe?

Usually because one side left the apostrophe as it is and the other wrote %27, so the signed strings differ. Encoding both values under RFC 3986 escapes ! ' ( ) * every time, so both sides produce the same text.

Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.

POSThttps://api.kit.forhosting.com/enc/url-rfc3986

Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.

curl -X POST https://api.kit.forhosting.com/enc/url-rfc3986 \
  -H "Authorization: Bearer $KIT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text":"hello world!'\''()"}'
{
  "text": "hello world!'()"
}
{
  "task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
  "type": "enc.url_rfc3986",
  "status": "queued",
  "_links": {
    "result": "/tasks/tsk_…/result"
  }
}

The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.

Per request$0.002

Published price — no tokens, no invented credits. A failed task is never charged.

HTTPCodeMeaning
401unauthorizedMissing or invalid API key.
402insufficient_balanceYour balance doesn't cover the task price.
404unknown_typeThat task type doesn't exist.
429rate_limitedToo many requests. Use the webhook instead of polling.

Many everyday tools follow JavaScript encodeURIComponent instead, which deliberately leaves exclamation marks, apostrophes, parentheses, and asterisks unescaped—characters that RFC 3986 classifies as sub-delims and that strict gateways, OAuth signers, and cross-language HTTP clients often expect to see as %21 %27 %28 %29 %2A. This capability implements the strict RFC 3986 map both ways: encode turns every non-unreserved UTF-8 byte into uppercase %HH, and decode restores plain text while failing fast on incomplete or non-hex percent sequences. Use it when your contract says “percent-encode per RFC 3986,” when you must match a non-JavaScript peer that only keeps the six unreserved punctuation marks, or when you need a single free browser tool and paid API that agree byte-for-byte on the same pure function. Pricing for successful API calls is the published base of $0.002 per item; validation failures are not billed.

How RFC 3986 percent-encoding differs from encodeURIComponent

A trailing bare percent, a sequence such as %G1, or invalid UTF-8 after expansion raises invalid_input with a position-aware message instead of returning half-decoded garbage. The path is pure string work with no network, no random seeds, and no wall-clock timestamps, so identical inputs always produce identical JSON. Successful API pricing is the published base of $0.002 per item.

What you send and what you get back

Send a required string field named text and an optional mode field. Mode encode percent-escapes text under the RFC 3986 unreserved rule and returns the transformed string in result. Mode decode validates every percent sequence, then reverses encoding and returns plain UTF-8 text in result. Classic checks include encoding a phrase that contains spaces and bangs so you can see %20 and %21 side by side, decoding caf%C3%A9%21 back to café!, and rejecting a string that ends with a bare percent or contains %ZZ. When mode is omitted, encode is the default so a single payload still does useful work. The response echoes mode and the original text, includes result and the length of result, and labels the contract with standard set to RFC 3986, a short unreserved summary, and also_escaped listing the four sub-delim characters that distinguish this map from encodeURIComponent. Missing text, non-string objects, unsupported mode values, strings longer than the documented maximum, incomplete percent escapes, non-hex digits after a percent sign, and host-level errors on invalid decoded UTF-8 all fail with invalid_input and a clear English message. Validation failures do not consume prepaid balance. Successful API pricing is the published base of $0.002 per item, matching other parse-tier encoders in the catalog.

Where strict RFC 3986 encoding shows up in real work

Because this capability is a pure parse engine, API pricing is the published base of $0.002 per successful item and failed validation does not consume balance.

Cross-language golden fixtures

Generate encode and decode vectors that Python, Go, Java, and Rust URL libraries agree on, including the sub-delim characters browsers often leave literal.

What happens if a percent sequence is malformed?

Decode fails with invalid_input, naming the position and the bad escape (for example an incomplete % or non-hex digits). Nothing is charged for validation failures.

Read the full KIT documentation →