Remove ANSI escape codes from terminal text and logs
Terminal output often contains invisible ANSI control sequences that add colors, bold text, cursor movement, window titles, and other display effects.
Run — free
Those instructions are useful in an interactive shell but become distracting characters when logs are copied into tickets, reports, search indexes, or datasets. This tool removes ANSI color and formatting escape codes while preserving the actual message, spaces, and line breaks. Paste output for a quick browser-side cleanup, or send it through the API when plain-text normalization belongs in an automated workflow.
Turn styled terminal output into useful plain text
Command-line programs frequently detect a terminal and decorate their output with color, emphasis, cursor controls, hyperlinks, or title-setting instructions. The display interprets those bytes, so a person sees a neat status message rather than the underlying control syntax. Problems appear when that same output is redirected, copied from a build system, stored in a database, or pasted into a support case. Escape sequences may surface as bracketed fragments, interfere with searches, inflate diffs, and make machine processing unreliable. This remover scans the supplied text and discards recognized ANSI control sequences while retaining ordinary Unicode characters, whitespace, and line structure. It handles common Select Graphic Rendition color codes as well as broader Control Sequence Introducer commands, Operating System Command strings, and related terminal control forms. The result is suitable for reading, copying, indexing, comparing, or passing to a downstream parser without display instructions mixed into the content.
How the deterministic scanner treats escape sequences
The cleaner reads the text from beginning to end once. When it encounters an ESC introducer or an equivalent single-byte C1 control, it checks the byte ranges defined for terminal control syntax and consumes the complete sequence. CSI commands are recognized through their parameter, intermediate, and final bytes, which covers familiar forms such as color changes, resets, erased lines, and cursor movement without maintaining a fragile list of individual commands. String controls such as OSC, DCS, SOS, PM, and APC are removed through their BEL or String Terminator boundary; an unterminated string control is treated as control data through the end of the input. Ordinary text is copied exactly, including emoji, non-Latin scripts, tabs, carriage returns, and newlines. The response also reports how many control sequences were removed and whether any change occurred, making it easy for an automated pipeline to record cleanup without comparing two potentially large strings. No terminal is emulated, so cursor movement does not rearrange visible characters; the tool removes instructions and preserves the textual payload order.
Use clean output safely in logs and automation
Use this capability immediately after capturing output from a process that may force color or formatting, especially when you cannot change that process to emit plain text. The cleaned value can go into a log aggregator, full-text index, incident report, snapshot test, notification, or structured extraction step. Because the algorithm is deterministic, identical input always produces identical output, which is important for build artifacts and regression comparisons. It performs no network requests, does not execute the supplied text, and does not interpret shell commands embedded in it. Remember that removing ANSI sequences is normalization, not security sanitization for every destination: HTML, SQL, CSV, and shell contexts each have their own escaping requirements. Also note that terminal applications can overwrite lines with carriage returns or backspaces; those ordinary control characters are preserved because they are not ANSI escape sequences. If you need a rendered transcript that reconstructs cursor positioning, use a terminal emulator before exporting plain text. For routine colorized logs, this focused cleanup keeps meaningful words and layout while removing presentation noise.
What you can do with it
Clean continuous-integration logs
Remove color and cursor commands before attaching build output to an issue, report, or searchable archive.
Stabilize snapshot comparisons
Normalize decorated command output so tests compare the message content rather than environment-dependent terminal styling.
Prepare logs for text processing
Feed readable plain text into search, classification, parsing, or alerting steps without ANSI instructions polluting tokens and fields.
FAQ
What does the tool remove?
It removes ANSI escape sequences used for colors, text attributes, cursor controls, terminal commands, hyperlinks, and control strings.
Does it preserve line breaks and Unicode text?
Yes. Ordinary characters, including Unicode text, tabs, carriage returns, and line feeds, remain in their original order.
Will cursor movement be rendered before cleaning?
No. The tool removes terminal instructions but does not emulate a screen or rearrange characters according to cursor movement.
What happens to an unterminated OSC or other string control?
The control sequence and everything after its introducer are removed because the remaining content cannot be distinguished safely from its payload.
Can I use the cleaned result directly as HTML or a shell command?
Do not assume so. ANSI removal is not a replacement for destination-specific escaping or validation.
How much does an API request cost?
Each API request costs $0.002. The same deterministic cleaner can also run in your browser.
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-ansi \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"\u001b[32mBuild passed\u001b[0m\n\u001b[1;33m2 warnings\u001b[0m"}'const res = await fetch("https://api.kit.forhosting.com/str/remove-ansi", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"text": "\u001b[32mBuild passed\u001b[0m\n\u001b[1;33m2 warnings\u001b[0m"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/str/remove-ansi",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"text": "\u001b[32mBuild passed\u001b[0m\n\u001b[1;33m2 warnings\u001b[0m"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/str/remove-ansi", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"text":"\\u001b[32mBuild passed\\u001b[0m\\n\\u001b[1;33m2 warnings\\u001b[0m"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"text":"\u001b[32mBuild passed\u001b[0m\n\u001b[1;33m2 warnings\u001b[0m"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/str/remove-ansi", 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": "\u001b[32mBuild passed\u001b[0m\n\u001b[1;33m2 warnings\u001b[0m"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "str.remove_ansi",
"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. |