Remove accents from text
Strip accents to get plain letters: café naïve São Paulo becomes cafe naive Sao Paulo, with 3 accents removed. Special letters such as æ and ł are converted as well, while digits and emoji stay as they are. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Text
- café naïve São Paulo
- Result
- cafe naive Sao Paulo
- Length
- 20
- Original length
- 20
- Changed count
- 3
Removing accents and other diacritical marks is a everyday hygiene step when you need plain ASCII text for identifiers, search keys, filenames, CSV exports, or systems that still choke on UTF-8 edge cases. This tool takes the text you enter, decomposes Unicode characters, strips combining marks, applies a fixed Latin transliteration table for letters that do not fully reduce with normalization alone, and returns the unaccented string together with length and change metadata. Digits, most punctuation, emoji, and unmapped scripts pass through unchanged; only diacritic and mapped Latin forms are simplified.
How accent removal works under the hood
Accent stripping is not a single character lookup; it is a short deterministic pipeline. First the engine applies Unicode Normalization Form D (NFD), which separates base letters from their combining diacritical marks—so é becomes e plus a combining acute accent, ñ becomes n plus a combining tilde, and ü becomes u plus a combining diaeresis. Second, every combining mark in the common mark ranges is deleted, leaving the bare base characters for the vast majority of Western European, Central European, and Vietnamese tone-marked Latin text.
Third, a fixed transliteration table rewrites letters that survive NFD without becoming ASCII: Nordic and Icelandic forms such as ø, æ, ð, and þ; German sharp s; French and Latin ligatures œ; Polish and Slavic stroke letters such as ł and đ; and a few Maltese and horned Vietnamese bases. The table is case-preserving where both cases exist (Æ becomes AE, æ becomes ae). Digits, spaces, punctuation, emoji, and scripts outside the map pass through unchanged, so Cyrillic or CJK text is not inventively romanized—that is a different product intent.
Empty strings fail validation before any transform runs. Because the path is pure parse work over strings, latency stays sub-millisecond for typical form sizes and the published cost model is analytic rather than model-token based.
Where remove-accents tools show up in real work
Product and growth teams fold display names and city fields into ASCII keys before uniqueness checks so José and Jose do not create confusing near-duplicates in systems that compare byte-wise. Search and tagging systems strip diacritics from query strings and facet labels so filters match regardless of whether editors typed resume or résumé. Data engineers cleaning CRM exports, spreadsheets, and legacy databases often force free-text columns to unaccented forms before joining on soft keys or loading into warehouses that still prefer ASCII collations for certain indexes.
Content and localization teams prepare ASCII fallbacks for filenames, URL path segments (when they are not using a dedicated slug tool), email subjects on picky relays, and CSV files opened in tools that mangle UTF-8. If you later need full URL slugify with hyphens and lowercasing, case conversion alone, language detection, or phonetic romanization of non-Latin scripts, treat those as separate search intents and landings rather than overloading this remove-accents-from-text page.
What you can do with it
Normalize names and cities for matching
Strip diacritics from people and place names before uniqueness checks so José/Jose and São Paulo/Sao Paulo align on soft keys.
Search and filter consistency
Fold query strings and facet labels so filters match whether users type accented or plain ASCII text.
FAQ
What does remove accents from text do?
It strips diacritical marks and maps common Latin specials so accented letters become plain ASCII (é→e, ñ→n, ü→u, æ→ae, ł→l, …) and returns the unaccented string plus change metadata.
What happens if I send empty text?
Empty strings are rejected so clients notice missing fields instead of receiving a silent empty result.
Does it change case or make URL slugs?
No. Case is preserved (Café becomes Cafe, not cafe). It does not insert hyphens or percent-encode for URLs; use a dedicated slug or lowercase tool for those intents.
What does it cost?
The browser tool is free and runs locally.
What happens to letters like æ or ł that have no accent?
A fixed table rewrites them into plain Latin letters, keeping upper and lower case: Æ becomes AE, æ becomes ae, and Łódź becomes Lodz. Nordic, German and Polish forms are covered this way.
Related tools
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, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/str/remove-accents \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"café naïve São Paulo"}'const res = await fetch("https://api.kit.forhosting.com/str/remove-accents", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"text": "café naïve São Paulo"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/str/remove-accents",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"text": "café naïve São Paulo"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/str/remove-accents", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"text":"café naïve São Paulo"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"text":"café naïve São Paulo"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/str/remove-accents", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"text": "café naïve São Paulo"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "str.remove_accents",
"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. |
Technical notes
Empty input is rejected with a clear validation error instead of silently returning an empty payload, which protects clients that forgot to bind a field. No network round-trips inside the engine, no random seeds, and no clock dependence—identical text always produces identical JSON.
How accent removal works under the hood
The algorithm walks the string once after normalization, builds the result, then computes changed, changed_count, and accents_removed so pipelines can detect no-ops without re-scanning. Extremely long payloads above the documented character cap also fail with invalid_input so a single request cannot monopolize Worker memory.
What you send and what you get back
Send a single required field named text containing the non-empty string you want to unaccent. Numbers and booleans are coerced to their decimal or true/false text forms; objects, arrays, NaN, and Infinity are rejected. Classic checks include café becoming cafe, naïve becoming naive, São Paulo becoming Sao Paulo, Müller becoming Muller, ñoño becoming nono, crème brûlée becoming creme brulee, and Łódź becoming Lodz after stroke mapping. Aliases such as input, value, data, s, message, string, content, and body are accepted for convenience when wiring older clients. On success the response echoes the original text, the unaccented result, the result length, the original length, a boolean changed flag, a changed_count of differing positions (including length deltas for multi-letter expansions such as æ to ae), accents_removed as a count of combining marks stripped plus mapped source letters, and operation set to remove_accents. When the input already had no diacritics and no mapped Latin specials, result equals text, changed is false, and accents_removed is zero—useful as a no-op detector in ETL guards. Wire the free browser form for quick paste-and-copy work, then call the identical contract from scripts when you normalize bulk CSV columns, search keys, or API payloads. Pricing for successful API calls is the published base of $0.002 per item; validation failures including empty text do not consume prepaid balance.
Where remove-accents tools show 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.
Integration use cases
Clean CSV and API free-text columns
Unaccent tags, titles, and soft-join fields in bulk pipelines with the same result shape as the browser tool.
Technical questions
Will already-plain ASCII text change?
No. If there are no diacritics and no mapped specials, result equals the original text, changed is false, and accents_removed is zero.