Extract lines matching regex
In a log with INFO, WARN and ERROR lines, the pattern ^ERROR\b keeps just the 2 error lines out of 4, untouched and in order. Each line is tested on its own, so a wildcard never spills into the next record. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Pattern
- ^ERROR\b
- Result
- ERROR database unavailable ERROR request timed out
- Matched count
- 2
- Total lines
- 4
Extract lines matching a regular expression when a large log, report, configuration dump, or structured text block contains far more information than you need. Supply the text, a JavaScript regex pattern, and optional flags; the capability tests each complete line and returns only the matching lines in their original order. It accepts common LF, CRLF, and CR line endings, preserves the content of selected lines, and reports both matched and total line counts. Processing is deterministic and local, with no model or network dependency.
Write a pattern for the lines you actually want
The pattern is applied independently to every complete line, which makes anchors especially useful. Start a pattern with ^ when the meaningful token must appear at the beginning of a line, and end it with $ when the final characters matter. For example, ^ERROR\b selects conventional error records without also accepting a label such as ERRORS, while \.csv$ keeps filenames ending in that extension.
You provide regular expression source rather than slash notation, so enter ^WARN, not /^WARN/. Optional JavaScript flags are supplied separately. The i flag makes matching case-insensitive; other supported runtime flags retain their standard JavaScript meaning.
Each selected line is returned unchanged and in its original position relative to other matches. Nonmatching lines disappear, but the tool does not trim, rewrite, sort, deduplicate, or interpret the content. This narrow contract is valuable for automation because the result is a predictable subset of the source rather than a summary that may omit important evidence.
Filter logs and structured text without changing the evidence
Line-oriented filtering is a natural fit for application logs, command output, delimited exports, test reports, and configuration files. A support engineer can isolate request identifiers, status codes, or severity labels before attaching a concise excerpt to an incident. A developer can retain failed assertions from a long test run.
An operations pipeline can select records whose timestamps, hostnames, or component prefixes satisfy a known convention. Because matching happens against one line at a time, a wildcard does not accidentally flow into the next record. LF, Windows CRLF, and bare CR boundaries are recognized, and the returned text uses stable LF separators so downstream comparisons behave consistently across platforms.
Blank lines can be selected deliberately with a pattern such as ^$. A final newline is treated as a terminator rather than an extra empty record, preventing an ordinary text file ending from inflating the total line count. Alongside the joined result, the response includes an array of selected lines plus matched and total counts, giving scripts convenient data and useful assertions without requiring another parsing pass.
Validate patterns and integrate the result safely
The capability rejects missing text, empty text, missing or empty patterns, unsupported or duplicate flags, incompatible Unicode modes, and regular expressions that the JavaScript engine cannot compile. A successful zero-match response is still useful: it contains an empty result, an empty lines array, a matched count of zero, and the number of lines inspected. When building a pipeline, test a new expression against representative samples, anchor it where the record format permits, and avoid unnecessarily ambiguous nested repetitions.
The algorithm uses no network, randomness, clock, or language model, so identical inputs produce identical outputs.
What you can do with it
Isolate error log entries
Keep only lines beginning with an error severity or containing a specific request identifier before incident review.
Select structured records
Extract rows whose prefixes, status fields, filenames, or identifiers satisfy a precise regular expression.
Reduce test output
Retain failed assertions and diagnostic markers from a long build log while preserving their original order.
FAQ
Should I include slashes around the regular expression?
No. Submit only the pattern source, such as ^ERROR\b. Put flags such as i in the separate flags field.
Does the pattern run against each line or the entire text?
It runs independently against each complete line. A line is returned once when the expression matches anywhere in that line.
Are matching lines modified?
No. Their characters and order are preserved. Only line separators in the joined result are normalized to LF.
How much does it cost?
You can run the same deterministic filtering free in the browser.
How do I make the match ignore upper and lower case?
Add the i option, which you enter separately from the expression. With it, ^error also keeps lines that start with ERROR or Error. Other standard regular expression options keep their usual meaning.
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/extract-lines-matching \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"INFO server started\nERROR database unavailable\nWARN retrying\nERROR request timed out","pattern":"^ERROR\\b"}'const res = await fetch("https://api.kit.forhosting.com/str/extract-lines-matching", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"text": "INFO server started\nERROR database unavailable\nWARN retrying\nERROR request timed out",
"pattern": "^ERROR\\b"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/str/extract-lines-matching",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"text": "INFO server started\nERROR database unavailable\nWARN retrying\nERROR request timed out",
"pattern": "^ERROR\\b"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/str/extract-lines-matching", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"text":"INFO server started\\nERROR database unavailable\\nWARN retrying\\nERROR request timed out","pattern":"^ERROR\\\\b"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"text":"INFO server started\nERROR database unavailable\nWARN retrying\nERROR request timed out","pattern":"^ERROR\\b"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/str/extract-lines-matching", 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": "INFO server started\nERROR database unavailable\nWARN retrying\nERROR request timed out",
"pattern": "^ERROR\\b"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "str.extract_lines_matching",
"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
Use the browser tool for quick investigation or call the API for $0.002 per successful request.
Validate patterns and integrate the result safely
Those cases return invalid_input rather than silently producing an empty result, so a typo in an automated rule is distinguishable from a valid pattern that simply found nothing. Then consume the lines array when you need structured JSON, or use the joined result when passing filtered text to a file, ticket, or another command. API automation costs $0.002 for each successful request, while interactive browser use is free.
Technical questions
What happens when no lines match?
The request succeeds with an empty result, an empty lines array, matched_count set to zero, and the inspected total_lines count.