Count numbers in text
Count Numbers in Text scans ordinary prose, reports how many separate numeric groups it contains, and returns the exact matches in reading order.
Run — free
It recognizes whole numbers, signed values, standard decimals, and leading-dot decimals without attempting to interpret the surrounding words. That makes it useful when you need a quick content summary, a lightweight extraction step, or a repeatable check before sending text into a larger data workflow. The same deterministic rules apply every time, whether the input is a sentence, report, log excerpt, or pasted table.
What the counter recognizes as a number
The scanner treats each contiguous integer or decimal group as one match. Whole values such as 42, signed values such as -7 and +12, ordinary decimals such as 19.95, and leading-dot decimals such as .75 are recognized. A run of digits stays together, so 2026 counts once rather than four times. The sign belongs to a number when it appears immediately before the numeric group. Returned matches preserve their original text and order, which means you can see exactly what produced the total instead of receiving an unexplained count. The rules intentionally focus on simple integer and decimal notation. Thousands separators, currency symbols, percentages, units, and surrounding punctuation are not normalized or interpreted. For example, a currency symbol remains outside the match while its following numeric group is counted. Scientific notation is not combined into a special numeric value; its visible numeric groups are scanned according to the same straightforward pattern. This narrow definition makes results predictable for content audits and extraction pipelines, especially when the source mixes prose, labels, and measurements.
How to read and verify the result
Send one text string and read the returned count for the summary. The accompanying matches array lists every detected group from left to right, retaining signs, decimal points, and digits exactly as written. That second field is useful for quality control: if a document produces an unexpected count, you can inspect the matches immediately and identify whether the source uses notation outside the supported rules. Empty text is valid and returns zero with an empty array, while a missing or non-string text field is rejected as invalid input. This distinction prevents absent data from being silently mistaken for a document containing no numbers. The implementation performs one bounded scan and does not make network requests, call a model, use locale-dependent parsing, or modify the supplied text. Consequently, repeated calls with the same string produce the same JSON. When integrating the endpoint, store the match list alongside the count if traceability matters. If only a dashboard total is needed, consume the count and discard the list. For very structured numeric formats, follow this counter with a domain-specific parser rather than assuming each returned string is already a validated business value.
Using number counts in practical workflows
A number count is a compact signal that fits many lightweight checks. Content teams can compare drafts and confirm that a supposedly data-rich summary still contains the expected quantity of figures. Analysts can scan copied notes before manually transferring measurements, while developers can use the match array as a first extraction pass over logs, tickets, or plain-text exports. In ingestion systems, the result can support simple routing: text with no numeric groups may follow a narrative path, while text containing several groups can be queued for deeper parsing. The endpoint is also helpful in tests where a generated report should contain a stable number of numeric tokens even though the actual values change. Remember that this tool counts notation, not meaning. A date such as 2026-07-25 contains three numeric groups, because punctuation separates the year, month, and day. A version label, identifier, or number embedded beside letters may still contribute a numeric group. Those behaviors are useful for broad extraction, but they may not match every semantic definition of a number. Use the returned evidence to apply any domain rule afterward. Browser use is free, and automated API requests use the displayed $0.002 base price, making the same operation suitable for an occasional paste or a repeatable pipeline.
What you can do with it
Summarize a report
Count the integer and decimal groups in a narrative report and inspect the exact figures in reading order.
Preflight extracted text
Check whether OCR output or copied notes contain the expected amount of numeric material before deeper parsing.
Test generated content
Assert that a template or generated status update contains a stable number of numeric tokens even when values vary.
FAQ
What does it cost?
It is free to run in your browser on this page. An API request uses the displayed $0.002 base price.
Are decimals counted as one number?
Yes. A standard decimal such as 12.5 or a leading-dot decimal such as .5 counts as one numeric group.
Do plus and minus signs belong to matches?
Yes, when a plus or minus sign appears immediately before the digits or leading decimal point, it is preserved in the match.
What happens with empty text?
An empty string is valid and returns a count of zero and an empty matches array. A missing or non-string text field is rejected.
Does it understand dates, currencies, or scientific notation?
It does not interpret meaning or locale-specific formats. It counts the simple integer and decimal groups visible inside those strings and returns them for inspection.
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/count-numbers \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"Revenue rose from 12.5 to 18 units across 3 regions."}'const res = await fetch("https://api.kit.forhosting.com/str/count-numbers", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"text": "Revenue rose from 12.5 to 18 units across 3 regions."
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/str/count-numbers",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"text": "Revenue rose from 12.5 to 18 units across 3 regions."
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/str/count-numbers", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"text":"Revenue rose from 12.5 to 18 units across 3 regions."}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"text":"Revenue rose from 12.5 to 18 units across 3 regions."}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/str/count-numbers", 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": "Revenue rose from 12.5 to 18 units across 3 regions."
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "str.count_numbers",
"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. |