# Count occurrences characters words or lines in a text

`POST /v1/count/string`

Counts how many times a text appears (case can be ignored), how many characters there are (with or without spaces), how many words or how many lines. Occurrences do not overlap by default, so aa in aaaa is 2; switch overlapping on to get 3. One final line break does not add a line.

## Request body

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| text | string | yes | The text |
| mode | one of: substring, characters, words, lines | yes | substring, characters, words or lines |
| value | string | no | For substring: the text to count |
| ignore_case | boolean | no | For substring: treat upper and lower case as equal (default `false`) |
| overlapping | boolean | no | For substring: count overlapping occurrences. Off by default, so aa in aaaa is 2; on, it is 3 (default `false`) |
| include_spaces | boolean | no | For characters: count spaces, tabs and line breaks. False counts the rest only (default `true`) |

## Example request

A request body that works, as JSON.

```json
{
  "text": "Ship the report. Ship the invoice. Ship the rest.",
  "mode": "substring",
  "value": "Ship"
}
```

## Code samples

Replace YOUR_TOKEN with your access token.

### curl

```shell
curl -X POST 'https://api.skillfulsardine.com/v1/count/string' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  --data-raw '{
  "text": "Ship the report. Ship the invoice. Ship the rest.",
  "mode": "substring",
  "value": "Ship"
}'
```

### PowerShell

```powershell
$body = @'
{
  "text": "Ship the report. Ship the invoice. Ship the rest.",
  "mode": "substring",
  "value": "Ship"
}
'@
$response = Invoke-RestMethod -Method Post -Uri 'https://api.skillfulsardine.com/v1/count/string' `
  -Headers @{ Authorization = 'Bearer YOUR_TOKEN' } `
  -ContentType 'application/json; charset=utf-8' `
  -Body ([System.Text.Encoding]::UTF8.GetBytes($body))
$response | ConvertTo-Json -Depth 10
```

### Python

```python
import requests

payload = {
    "text": "Ship the report. Ship the invoice. Ship the rest.",
    "mode": "substring",
    "value": "Ship",
}

response = requests.post(
    "https://api.skillfulsardine.com/v1/count/string",
    headers={"Authorization": "Bearer YOUR_TOKEN"},
    json=payload,
    timeout=30,
)
print(response.json())
```

### JavaScript

```javascript
const response = await fetch("https://api.skillfulsardine.com/v1/count/string", {
  method: "POST",
  headers: {
    "Authorization": "Bearer YOUR_TOKEN",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
  "text": "Ship the report. Ship the invoice. Ship the rest.",
  "mode": "substring",
  "value": "Ship"
}),
});
const result = await response.json();
console.log(result);
```

### Node

```javascript
// Node 18 or later. Save as call.mjs and run: API_TOKEN=... node call.mjs
const token = process.env.API_TOKEN;

const response = await fetch("https://api.skillfulsardine.com/v1/count/string", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${token}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
  "text": "Ship the report. Ship the invoice. Ship the rest.",
  "mode": "substring",
  "value": "Ship"
}),
});
const result = await response.json();
console.log(result);
```

### Rust

```rust
// Cargo.toml: reqwest = { version = "0.12", features = ["blocking", "json"] }, serde_json = "1"
fn main() -> Result<(), Box<dyn std::error::Error>> {
    let body: serde_json::Value = serde_json::from_str(r#"{
  "text": "Ship the report. Ship the invoice. Ship the rest.",
  "mode": "substring",
  "value": "Ship"
}"#)?;
    let response = reqwest::blocking::Client::new()
        .post("https://api.skillfulsardine.com/v1/count/string")
        .bearer_auth("YOUR_TOKEN")
        .json(&body)
        .send()?;
    println!("{}", response.text()?);
    Ok(())
}
```

### Swift

```swift
import Foundation

var request = URLRequest(url: URL(string: "https://api.skillfulsardine.com/v1/count/string")!)
request.httpMethod = "POST"
request.setValue("Bearer YOUR_TOKEN", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = Data(#"""
{
  "text": "Ship the report. Ship the invoice. Ship the rest.",
  "mode": "substring",
  "value": "Ship"
}
"""#.utf8)

let (data, _) = try await URLSession.shared.data(for: request)
print(String(decoding: data, as: UTF8.self))
```

## Response

The fields inside `data` of a successful response.

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| count | integer | yes | How many |

## Example response

A real answer from the operation, as JSON. The fields in the table above are inside `data`.

```json
{
  "data": {
    "count": 3
  },
  "errors": null,
  "meta": {
    "request_id": "5dcdaf73-5070-4112-9259-1f1dbb32af7a",
    "timestamp": "2026-10-27T07:19:42.158532Z",
    "version": "2026-03-26"
  },
  "pagination": null
}
```

## Responses

| Status | When it happens |
| --- | --- |
| 200 | Successful Response |
| 400 | The body respects the operation schema, but the use case rejected it. Each problem is one ApiError entry |
| 413 | The request is larger than the request size limit of the API allows |
| 422 | The body does not respect the operation schema. Each problem is one ApiError entry with the code validation_error |
| 500 | Something failed inside the server and was not an input problem. The same envelope, errors may be empty |

---
Source: https://skillfulsardine.com/developers/api/count-text/