Normalize ellipsis characters and three periods
Ellipsis styles often become mixed when text passes through editors, content systems, copied documents, and publishing tools.
Run — free
This capability standardizes those omission marks without rewriting any other punctuation. Choose whether every sequence of three consecutive periods should become the single Unicode ellipsis character, or whether every ellipsis character should expand to three ordinary periods. The conversion is deterministic, preserves surrounding spaces and words exactly, and reports how many replacements were made, making it suitable for both one-off proofreading and repeatable text-processing pipelines.
Choose the ellipsis style your destination expects
A visual ellipsis can be represented in two common ways: three full-stop characters, written as <code>...</code>, or one Unicode ellipsis character, written as <code>…</code>. They may look similar in a paragraph, but they are not the same data. Search tools, character limits, typography rules, and downstream validators can treat them differently. Select <code>periods_to_ellipsis</code> when a publication, design system, or house style calls for the compact Unicode character. Select <code>ellipsis_to_periods</code> when a plain-text format, legacy system, source-code convention, or restricted character set expects ASCII punctuation. The first mode is the default because it produces the dedicated typesetting character. The selected direction is applied throughout the supplied text, including multiple occurrences on one line and occurrences across multiple lines. Words, whitespace, quotation marks, and all punctuation other than the requested ellipsis form remain unchanged, so the operation is focused and predictable rather than a general copy-editing pass.
Understand exactly what gets replaced
In <code>periods_to_ellipsis</code> mode, each non-overlapping sequence of exactly three consecutive period characters encountered by the scan becomes one ellipsis character. A run of six periods therefore becomes two ellipsis characters, while one or two periods remain untouched. In <code>ellipsis_to_periods</code> mode, every Unicode ellipsis character becomes three periods. The tool does not infer whether punctuation expresses hesitation, an omitted quotation, a leader, or an accidental typing pattern; it performs the explicit character conversion you requested. It also does not add or remove spaces around the mark. That restraint matters because spacing conventions vary between editorial styles and languages, while this capability is intended to normalize representation only. The response includes the converted text, the canonical mode name, and a replacement count. A count of zero is a valid result and means the source did not contain the form targeted by the chosen direction. You can use that count to detect changed records without comparing entire documents.
Use normalization safely in publishing workflows
For a single passage, paste the source text, choose the intended direction, and review the returned text before placing it in your layout. For automated work, call the same operation immediately after import or just before export so every document crosses a clear normalization boundary. Applying one declared style at a consistent stage prevents editors and renderers from repeatedly introducing a mixture of representations. The transformation is idempotent for a fixed direction: running <code>periods_to_ellipsis</code> again on its own result makes no further changes, and the same is true for <code>ellipsis_to_periods</code>. Be aware that reversing direction later changes every matching mark, not only marks produced by an earlier call, because no provenance is embedded in plain text. The algorithm uses no network, model, randomness, or clock, so identical inputs and modes always produce identical outputs. Browser use is convenient for manual cleanup, while API requests cost $0.002 each and fit batch publishing, migration, lint-fix, and content-ingestion jobs.
What you can do with it
Apply a publication style guide
Convert mixed three-period sequences into the dedicated ellipsis character before articles enter layout and proofreading.
Prepare text for an ASCII-only system
Expand Unicode ellipsis characters into ordinary periods before sending copy to a legacy or restricted text pipeline.
Normalize imported content
Run one predictable punctuation rule across records copied from editors, documents, feeds, and content management systems.
FAQ
What does this capability cost?
Each API request costs $0.002. You can also run the browser version on the page.
Does it change spaces around an ellipsis?
No. It changes only the selected period or ellipsis characters and preserves surrounding whitespace exactly.
What happens to six consecutive periods?
In periods-to-ellipsis mode, the non-overlapping scan converts them into two ellipsis characters.
Will it alter single periods or decimal numbers?
Single periods and pairs of periods are unchanged. Only a sequence of three periods is targeted in the default direction.
Is running the same conversion twice safe?
Yes. For a fixed mode, the normalized output contains none of that mode's source pattern, so a second run makes zero replacements.
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/normalize-ellipsis \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"Wait... is that all?"}'const res = await fetch("https://api.kit.forhosting.com/str/normalize-ellipsis", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"text": "Wait... is that all?"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/str/normalize-ellipsis",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"text": "Wait... is that all?"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/str/normalize-ellipsis", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"text":"Wait... is that all?"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"text":"Wait... is that all?"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/str/normalize-ellipsis", 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": "Wait... is that all?"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "str.normalize_ellipsis",
"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. |