Number lines with a custom start and step
Custom line numbering is useful whenever ordinary one-by-one labels are not enough.
Run — free
Paste a passage, list, code sample, transcript, or citation block, choose the number for its first line, and choose how much each following number changes. The tool preserves the order and content of every line while adding predictable references that are easy to quote, compare, or paste into another document. It also handles descending and repeated values when your workflow requires them.
Choose a starting value that fits the surrounding document
The start setting controls the number attached to the first line. This matters when the text is an excerpt rather than a complete document. If an earlier section ended at line 240, for example, begin the next section at 241 and keep references continuous without inserting placeholder lines. A custom start is also helpful for classroom exercises, legal exhibits, interview transcripts, and staged code reviews where a pasted fragment must retain a meaningful position. Enter the source text exactly as it should appear, including intentional blank lines. The tool normalizes common newline styles so results remain stable across operating systems, but it does not trim, rewrite, wrap, or otherwise alter the original line content. Every line produced by splitting the supplied text receives a label, including an empty line and a final empty line created by a trailing newline. That explicit behavior makes later references unambiguous: the same input and settings always identify the same content with the same numbers.
Use the step to build more than a consecutive list
The step setting is added after each line, giving you direct control over the numbering sequence. A step of 1 creates familiar consecutive labels, while 5 produces 10, 15, 20, and so on when the start is 10. Larger gaps leave conceptual room for material that may be inserted later, which is useful in specifications, scripts, and review notes. Negative steps create descending references for countdowns or reverse-ordered excerpts. A zero step deliberately repeats the same label on every line when a shared section marker is more useful than a sequence. Both start and step must be integers within the published limits; accepting only integers avoids surprising fractional labels and makes the result straightforward to cite. Before returning output, the algorithm also verifies that the last generated value remains a safe integer. These rules keep long inputs deterministic and prevent silent numerical rounding, whether the capability runs in a browser or through an automated API workflow.
Copy a stable result into citations, listings, and reviews
The separator is the short piece of text placed between each generated number and its source line. The default period and space reads naturally in general lists, while a colon, tab, pipe, or bracket-like marker may fit code listings and citation formats better. The result includes one combined text value for immediate copying as well as an array of numbered lines for programs that need to process entries independently. It also reports the line count and the effective start, step, and separator, so an integration can record exactly how the result was produced. No network request, language model, clock, or random value participates in the transformation. Input size, line count, and separator length are bounded and checked before the response is built. This makes the capability suitable for repeatable publishing pipelines: store the settings beside a source revision, regenerate the numbered excerpt later, and receive identical labels whenever the source text itself has not changed.
What you can do with it
Continue a code listing
Start an extracted block at the line number used by the larger source file and create stable review references.
Prepare spaced specification clauses
Number requirements in increments such as ten so later clauses can be inserted between existing references.
Create citation-ready transcripts
Apply consistent labels to every transcript line, including intentional blank lines, before sharing an excerpt.
FAQ
What does one request cost?
Each API request costs $0.002. The browser implementation uses the same deterministic algorithm.
Can numbering count down?
Yes. Use a negative integer for step, such as -1 or -10.
Can every line receive the same number?
Yes. A step of zero repeats the starting value for every line.
Are blank lines removed?
No. Blank lines, including a final empty line caused by a trailing newline, are preserved and numbered.
Does the tool change line endings?
CRLF and CR line endings are normalized to LF so the output is consistent across platforms.
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/enumerate-lines-custom \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"First reference\nSecond reference\nThird reference"}'const res = await fetch("https://api.kit.forhosting.com/str/enumerate-lines-custom", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"text": "First reference\nSecond reference\nThird reference"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/str/enumerate-lines-custom",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"text": "First reference\nSecond reference\nThird reference"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/str/enumerate-lines-custom", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"text":"First reference\\nSecond reference\\nThird reference"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"text":"First reference\nSecond reference\nThird reference"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/str/enumerate-lines-custom", 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": "First reference\nSecond reference\nThird reference"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "str.enumerate_lines_custom",
"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 |
max_lines | 10000 |
max_separator_chars | 32 |
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. |