Find position of substring
In "The kit parses logs: ERROR at line 12, then INFO, then ERROR again." the first ERROR sits at index 21, line 1, column 22, and ends before 26. Dots and brackets are searched as plain text. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Find
- ERROR
- Index
- 21
- Start
- 0
- Length
- 67
- Find length
- 5
Finding the first occurrence of a phrase is the first step in almost every text pipeline: you locate a marker, then slice, parse, or highlight from that character index. This find-position-of-substring tool takes your source text and a non-empty search term and returns the zero-based character index of the first literal match, plus whether it was found, the exclusive end offset, and the one-based line and column so you can jump to the hit in an editor. Optional start lets you resume after a previous match. Optional case-insensitive matching covers mixed-case drafts. Empty search terms fail with invalid input so bulk jobs never treat the empty string as a match at every offset.
What find position of substring means and when to use it
Find position of substring means scan the source string from the left — or from an optional start offset — stop at the first non-overlapping literal match of a search term, and report the character index of that hit so a later step can slice, parse, or highlight from there. Matching is literal: if you search for a period, a parenthesis, or a bracket, those characters are plain text, not regular-expression syntax, so the tool stays predictable for non-developers and for pipelines that must never surprise on special characters.
Prefer this calculator when the search intent is find the position of a substring, string index of, locate first occurrence, or get the character offset of a token. Typical sources include log lines where you need the first ERROR marker, configuration snippets where a key must be found before a value is cut, HTML or markdown where a heading delimiter starts a section, and CSV or TSV cells where a delimiter or quoted field begins.
Optional case-insensitive matching folds letter case so the first Hello, HELLO, or hello is caught without listing variants. Do not use this product when you need to rewrite the match — that is a different SEO intent served by replace-first and find-and-replace tools — or when you need every occurrence listed, capture groups, lookarounds, or a multi-line regex engine.
Everyday uses and practical limits
Call the free in-browser find position of substring tool for paste checks, classroom demos, content QA, and quick locator work without installing a desktop utility or writing indexOf snippets in every language. A typical workflow finds the first section marker, reads index and end, then slices the heading that follows. Another workflow walks successive hits by sending the previous end as the next start, which locates the second and later occurrences without a replace-all tool.
Do not expect HTML-aware skipping of tags, structured document merge fields, grapheme-cluster indices, or locale-specific collation beyond standard ignore-case matching — those are separate problems. Authors shipping SDKs can document text and find as required fields and show a multi-match source where only the first index is returned plus an empty-find error example so integrators see both sides of the contract.
What you can do with it
Locate the first log or error marker
Parsers and support tools find the first ERROR, TODO, or delimiter, then slice or highlight from that character index without rewriting the file.
Resume a scan after a previous hit
Send the previous exclusive end as start to walk the second and later occurrences one by one in templates, logs, and configuration files.
FAQ
How do I find the position of a substring?
The response index is the zero-based character offset of the first match, or -1 if none.
Is the index zero-based or one-based?
index is zero-based, the same contract as JavaScript String indexOf, so you can pass it to slice. When a match is found, position is the one-based character number people expect in an editor, and line and column are one-based as well.
What happens if the search term is empty?
An empty find string is rejected so pipelines never treat the empty string as a match at every offset; those failures are not charged.
Is the find position of substring tool free?
The browser tool runs free on your device.
Does find support regular expressions?
No. The search term is always treated as a literal string. Periods, brackets, and other regex metacharacters match themselves so the behavior stays predictable for editors and bulk jobs.
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/index-of \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"The kit parses logs: ERROR at line 12, then INFO, then ERROR again.","find":"ERROR"}'const res = await fetch("https://api.kit.forhosting.com/str/index-of", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"text": "The kit parses logs: ERROR at line 12, then INFO, then ERROR again.",
"find": "ERROR"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/str/index-of",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"text": "The kit parses logs: ERROR at line 12, then INFO, then ERROR again.",
"find": "ERROR"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/str/index-of", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"text":"The kit parses logs: ERROR at line 12, then INFO, then ERROR again.","find":"ERROR"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"text":"The kit parses logs: ERROR at line 12, then INFO, then ERROR again.","find":"ERROR"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/str/index-of", 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": "The kit parses logs: ERROR at line 12, then INFO, then ERROR again.",
"find": "ERROR"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "str.index_of",
"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.
Limits
max_chars | 100000 |
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
What find position of substring means and when to use it
An empty search term raises invalid_input, which protects bulk jobs from the classic footgun of treating the empty string as a match between every character.
Input contract, empty search rejection, and reading the response
Optional start defaults to zero and is the zero-based UTF-16 index where the scan begins, so you can resume after a previous hit without rescanning the prefix. When a match is found the response also includes position as the one-based human index, end as the exclusive end offset, line and column as one-based editor coordinates, and matched as the exact slice at the hit so a case-insensitive search still shows the original casing. A missing match is a valid success: found is false and index is negative one, which is the honest result for a haystack that does not contain the needle. Use index with slice when a script will cut the remainder; use line and column when a UI should scroll to the hit; use found alone when a gate only cares whether the marker exists. Send a JSON body with the required string field text set to the source you want scanned and the required string field find set to a non-empty search term. Optional case_insensitive defaults to false for exact case; set it true when the first mixed-case draft should still match. Aliases are accepted for older clients: text also as input, value, s, content, source, or haystack; find as search, needle, substring, query, or pattern; start as from, from_index, or offset; case_insensitive as ignore_case, ci, or insensitive. Missing text, missing find, a non-string value, a negative or non-integer start, or an empty find string all raise invalid_input with a message that names the problem, and those failures are not charged on the prepaid API. Length is capped at one hundred thousand characters so browser and Worker scans stay bounded. On success the response always includes index as the zero-based character offset or negative one when none, found as a boolean, text and find as applied, start and case_insensitive as used, length and find_length as character lengths, and method always equal to index_of.
API usage, pricing, workflows, and practical limits
Use the prepaid KIT API when a CMS, ETL job, form backend, support desk, parser, or mobile client needs the same locator under balance at $0.002 per successful item; validation failures never consume balance after the engine rejects the request. Pair this endpoint with replace-first when a later step must rewrite only that hit, or with find-and-replace when every match must change, but keep find-position as its own landing so the SEO intent is not mixed with editors that mutate text.
Integration use cases
QA and deterministic fixtures
Test harnesses pin index, found, line, and column so a refactor that switches to replace, regex, or empty-find matching fails continuous integration immediately.