Encode and decode a URL
A single misplaced ampersand or unescaped space in a URL can silently break a redirect, a tracking pixel or an entire integration test suite. This URL encode API percent-encodes and decodes strings exactly the way RFC 3986 expects, so query parameters, path segments and form data survive the trip intact.
Run — free
Runs in your browser. Free, unlimited — your data never leaves this page.
Why percent-encoding still trips people up
Every language ships a built-in encode function, yet developers keep hitting the same wall: JavaScript's encodeURIComponent treats spaces differently than PHP's urlencode, and neither agrees on what a query string versus a path segment actually requires. Reserved characters like plus signs and tildes end up handled inconsistently across runtimes. Our dev.url_encode endpoint removes that ambiguity by applying one deterministic rule set, so the same input always produces the same output no matter which stack called it.
What the endpoint actually does
POST /dev/url-encode accepts a string and a direction, either encode or decode, and returns a task_id immediately since the job runs asynchronously. Under the hood it walks the input byte by byte, converting unsafe or reserved characters into their %XX percent-encoded form on the way out, or resolving %XX sequences back into readable text on the way in. Multi-byte UTF-8 characters, common in names, addresses and international content, are handled natively rather than mangled into question marks.
A brief note on where this format comes from
Percent-encoding predates most of today's web frameworks; it was formalized to let URLs, originally designed for a narrow ASCII character set, safely carry arbitrary bytes like spaces, ampersands and non-Latin scripts. That legacy is exactly why encoding rules feel inconsistent today: different specifications, URI syntax versus HTML form submission, diverged over decades, and most libraries only implement one of them well.
Where it fits in a pipeline
Teams call this endpoint before building outbound webhook URLs, when normalizing user-submitted links for storage, or when cleaning malformed query strings pulled from log files and third-party exports. Because results arrive by signed webhook or a signed link valid for 24 hours, you can drop it into a batch job that processes thousands of URLs without holding a connection open or polling for each one.
Reliability without the guesswork
Each request is billed only on success; a failed task is retried up to three times automatically and never charged if it still fails, so you are not stuck babysitting encoding edge cases from rare byte sequences. At $0.002 per request, running it across an entire URL dataset costs a predictable, published amount with no tiers to negotiate and no trial to expire.
What you can do with it
Building outbound webhook URLs
Encode dynamic query parameters, like customer emails or free-text tags, before appending them to a callback URL so the receiving server parses them correctly.
Cleaning scraped or imported links
Decode double-encoded URLs pulled from CSV exports or old databases to recover the original, human-readable address before re-storing it.
Normalizing user-submitted forms
Percent-encode search terms or file names entered by users so they can be safely embedded in redirect links and analytics tags.
Fixing malformed log data
Decode raw request URIs captured in server logs to make them readable during incident investigation or traffic analysis.
FAQ
What is the difference between URL encoding and URL decoding?
Encoding converts unsafe characters, like spaces, ampersands and accented letters, into %XX sequences so a URL is transmitted safely; decoding reverses that process back to readable text. This API supports both directions in one endpoint.
Is there a free tier for the URL encode API?
The tool above runs free in your browser. The API is paid — each call draws from your prepaid ForHosting KIT balance: top up from $10.00 (it never expires), pay each request's published price, and a call with no balance returns HTTP 402. No subscription, no tokens, and a failed task is never charged.
How much does it cost per request?
Each call to POST /dev/url-encode costs $0.002, billed only when the task completes successfully.
Does it handle non-Latin characters like Chinese or Arabic text?
Yes. The endpoint processes UTF-8 multi-byte sequences correctly, producing valid percent-encoded output for any script rather than dropping or corrupting characters.
How do I get the result back?
Every task returns its result via a signed webhook, the recommended method for automated pipelines, or a signed link valid for 24 hours if you prefer to fetch it manually.
What happens if my request fails?
The task is retried automatically up to three times. If it still fails, you receive a clear error and are not charged.
Can I encode a full URL or only individual parameters?
You can submit either a full URL or a single value like a query parameter; the endpoint encodes exactly the string you send without assuming structure.
Why not just use my language's built-in encode function?
Built-in functions vary by language in how they treat spaces, plus signs and reserved characters, which causes subtle bugs across mixed-stack systems; this endpoint applies one consistent rule set regardless of caller.
For developers — API access
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.
API endpoint
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, and soon from our app, email and Telegram.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/dev/url-encode \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"items":["valor-1","valor-2"]}'const res = await fetch("https://api.kit.forhosting.com/dev/url-encode", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"items": [
"valor-1",
"valor-2"
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/dev/url-encode",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"items": [
"valor-1",
"valor-2"
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/dev/url-encode", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"items":["valor-1","valor-2"]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"items":["valor-1","valor-2"]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/dev/url-encode", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"items": [
"valor-1",
"valor-2"
]
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "dev.url_encode",
"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.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |