# Content Readability Analyzer — Flesch, Gunning Fog & SEO (`perryay/content-readability-analyzer`) Actor

Analyze text content with Flesch-Kincaid, Gunning Fog, SMOG, Coleman-Liau, and Automated Readability Index. Get grade levels, reading ease scores, and SEO-friendly suggestions for content optimization.

- **URL**: https://apify.com/perryay/content-readability-analyzer.md
- **Developed by:** [Perry AY](https://apify.com/perryay) (community)
- **Categories:** Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.015 / readability analysis

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Content Readability Analyzer 📝

**Analyze text content using six academically validated readability algorithms — Flesch Reading Ease, Flesch-Kincaid Grade Level, Gunning Fog Index, SMOG Index, Coleman-Liau Index, and Automated Readability Index — to get precise US grade-level equivalents, reading ease scores, and actionable SEO suggestions in a single API call.** Built for SEO specialists, content editors, technical writers, educators, and accessibility officers, this actor provides objective, reproducible readability scoring that helps you optimize content for the right audience level, from elementary school through postgraduate.

---

### What does it do?

Content Readability Analyzer evaluates text using a comprehensive suite of six established readability formulas, each measuring text complexity from a different analytical angle. The **Flesch Reading Ease** score (0–100) measures how easy text is to read based on sentence length and syllable density — higher scores indicate simpler text. The **Flesch-Kincaid Grade Level** converts those same metrics into a US school-grade equivalent (e.g., 8.0 means an 8th grader can understand it). The **Gunning Fog Index** estimates years of formal education needed for first-pass comprehension by factoring in the percentage of complex words (three or more syllables). The **SMOG Index** — originally developed for healthcare literacy assessment and the most conservative of the six — uses a more stringent complex-word formula to produce the highest grade-level estimates. The **Coleman-Liau Index** takes a character-based approach (counting characters per 100 words instead of syllables), making it algorithmically distinct and particularly reliable for very short texts. Finally, the **Automated Readability Index (ARI)** combines characters-per-word with words-per-sentence to produce a grade level closely aligned with Flesch-Kincaid but with different sensitivity to word length.

Beyond per-algorithm scores, the actor computes a composite **A–F overall grade** by averaging the six algorithms into a single letter-grade classification with interpretations from "Very Readable" (A) to "Very Difficult" (F). Each result is accompanied by **contextual SEO suggestions** — for example, flagging when the Gunning Fog Index is too high (indicating too many complex words) or when the Flesch Reading Ease score falls below the threshold for general audiences. These suggestions tell you exactly which aspect of your writing needs adjustment: syllable density, sentence length, or vocabulary complexity. The actor's **heuristic-based English syllable counter** applies six distinct rules — handling silent 'e' endings, the syllabic 'le' sound, vowel-group counting, and silent endings like -ed, -es, and -ely — tuned for standard English prose with common vocabulary.

**Batch processing** supports scoring up to 100 texts in a single run with independent per-text results, consistent formatting, and a batch summary that includes the average Flesch Reading Ease and average grade level across all texts. This makes it ideal for content management system integrations, editorial pipelines, and large-scale content audits where manual scoring of hundreds of articles is impractical. Each text is analyzed independently, so a failed or empty input on one item does not interrupt the rest of the batch.

---

### Who is it for?

| Persona | What They Use It For |
|---------|----------------------|
| **SEO Specialist** | Optimizing blog posts and landing pages for target audience reading level; identifying content that is too complex or too simple for its intended search ranking; benchmarking competitor content readability |
| **Content Editor** | Enforcing a consistent readability threshold across all published content; catching complexity drift before publication; integrating readability gates into editorial workflows |
| **Technical Writer** | Auditing documentation, API guides, developer tutorials, and knowledge-base articles for accessibility to junior developers and non-native-English speakers; ensuring consistent tone across large documentation sets |
| **Educator & Curriculum Designer** | Validating textbooks, worksheets, e-learning modules, and assessment materials match the intended student grade level; flagging materials that need differentiation or enrichment |
| **UX Writer** | Reviewing error messages, onboarding tooltips, in-app copy, push notifications, and empty-state text for plain-language compliance; ensuring microcopy meets Flesch Reading Ease targets for the target product audience |
| **Accessibility Officer** | Producing objective compliance evidence for plain-language mandates including healthcare literacy standards (SMOG Index), US Plain Writing Act requirements, UK NHS content standards, and EU accessibility directives |
| **Linguistics Researcher** | Reproducible multi-algorithm scoring across large corpora for discourse analysis, genre comparison, diachronic readability studies, or regression analysis of text complexity trends |

---

### Why use this?

- **📊 Six algorithms, one call** — Flesch Reading Ease, Flesch-Kincaid Grade Level, Gunning Fog Index, SMOG Index, Coleman-Liau Index, and Automated Readability Index. Each algorithm has unique strengths for different use cases, and together they provide a complete picture of text complexity. No need to visit six separate calculators or install six different Python packages with incompatible APIs.

- **🎯 A–F composite grade with contextual suggestions** — In addition to per-algorithm scores, the actor computes an overall readability grade (A through F) by averaging the six algorithms into a single classification. Paired with targeted SEO suggestions that identify exactly which aspect of your writing needs adjustment — syllable density, sentence length, or vocabulary complexity — you get a complete readability prescription in one structured response that requires no manual interpretation.

- **📦 Batch processing for real-world content workflows** — Submit up to 100 texts in a single run and get independent, per-text scores with consistent formatting. Ideal for content management system integrations, editorial calendars, large-scale content audits, and CI/CD pipelines where scoring hundreds of articles one at a time is impractical. Includes a batch summary with average scores across all texts.

- **🔬 Intermediate statistics for deep analysis** — Beyond the headline scores, each result includes word count, sentence count, character count, average word length, and average sentence length. These intermediate statistics enable deeper analysis: syllable-per-word ratios, complex-word percentages, and character-density metrics that power custom readability models, downstream data pipelines, or academic regression studies.

- **⚡ Lightweight execution, production-ready** — Typical analysis completes in under 200 ms per text with minimal memory footprint (~50–100 MB). A full batch of 100 texts (average 500 characters each) finishes in 2–5 seconds, making it suitable for real-time use in publishing workflows, content management system integrations, and CI/CD pipelines where speed matters. No GPU required — runs efficiently on any Apify actor runtime.

- **🛡️ Error-resilient batch processing** — Empty texts, whitespace-only inputs, and zero-length edge cases return structured error objects with zeroed counts instead of raising exceptions. This allows batch runs with hundreds of items to continue uninterrupted, with each failed item clearly identifiable in the results array so you can inspect or retry only the problematic texts.

---

### Algorithms

#### Readability Formula Reference

| Algorithm | Range | What It Measures | Best For |
|-----------|-------|------------------|----------|
| **Flesch Reading Ease** | 0–100 | Sentence length + syllables per word. Higher scores = easier text. 90–100 = Very Easy (5th grade); 60–70 = Standard (Plain English); 30–50 = Difficult (College); 0–29 = Very Confusing (College Graduate) | General content, marketing copy, web writing, public-facing communications — the most widely recognized and cited readability metric globally |
| **Flesch-Kincaid Grade Level** | 0–20+ | Sentence length + syllables per word, converted to a US school grade level. A score of 8.0 means an 8th grader can read it | Technical documentation, educational materials, compliance documents, content targeting a specific grade level (target 7–9 for general audience) |
| **Gunning Fog Index** | 0–20+ | Words per sentence + percentage of complex words (3+ syllables). Estimates years of formal education needed for first-pass comprehension | Journalism, academic writing, professional communication, any context where vocabulary complexity and abstract terminology matter |
| **SMOG Index** | 0–20+ | Complex word count per 30 sentences. Originally developed for healthcare literacy assessment. The most conservative of the six algorithms — always returns the highest grade level | Medical content, legal documents, healthcare accessibility compliance, plain-language auditing, regulatory communications |
| **Coleman-Liau Index** | 0–20+ | Characters per 100 words + sentences per 100 words. Uses character counts instead of syllable estimation, making it algorithmically distinct from all other metrics | UX microcopy, error messages, UI labels, push notifications, and very short content where syllable-based algorithms are unreliable |
| **Automated Readability Index (ARI)** | 0–20+ | Characters per word + words per sentence, producing a US grade level. Uses character-level analysis rather than syllable counting | General readability assessment, cross-validation against Flesch-Kincaid, content with unusual or technical vocabulary where syllable heuristics may fail |

#### Scoring Breakdown

| Grade | Score Range | Interpretation | Recommended Action |
|-------|-------------|----------------|-------------------|
| A (Very Readable) | 80–100 | Elementary to early middle school level. Content flows naturally, sentences are short, vocabulary is common. Suitable for children ages 10–12 and general audiences | Suitable for broad consumer audiences. If targeting professionals, may feel oversimplified — consider adding depth |
| B (Readable) | 60–79 | Late middle school to early high school level (grades 7–9). Plain English — the sweet spot for most B2C and B2B content. Balanced sentence length and vocabulary | Ideal for most consumer and business content. Maintain this level for maximum reach and engagement |
| C (Moderate) | 40–59 | High school to early college level (grades 10–12+). Contains some specialized vocabulary and longer sentences. Appropriate for professional audiences | Suitable for industry publications, professional blogs, and technical content. Consider simplifying for broader audiences |
| D (Difficult) | 20–39 | College level. High syllable density, frequent complex words, and longer sentences. May challenge general readers significantly | Needs simplification for wider reach. Focus on reducing sentence length and replacing complex vocabulary with simpler alternatives |
| F (Very Difficult) | 0–19 | Postgraduate / specialist level. Dense with jargon, abstract terminology, and long, nested sentences. Likely to frustrate or lose non-expert readers | Strongly consider restructuring and simplifying. Break long sentences, reduce complex word count, and add transitional explanations |

---

### Input Parameters

| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `texts` | array of strings | Yes\* | — | Array of text strings to analyze for readability. Each text is scored independently. Maximum 100 texts per run. Duplicate or near-duplicate texts are not deduplicated — each array entry produces a separate result |
| `text` | string | Yes\* | — | A single text string to analyze. Alternative to `texts` for quick one-off analysis. If both `text` and `texts` are provided, `texts` takes precedence and `text` is appended as an additional entry |
| `language` | string | No | `en` | Language code for the text (default: `en` for English). Currently only English is fully supported with a dedicated syllable counter. Non-English text will still produce scores, but accuracy may be reduced as all algorithms are English-language based. This field is echoed in the output as-is |

> \* Provide at least one of `text` or `texts`. If both are provided, `texts` takes precedence and `text` is appended as an additional entry in the analysis array.

> **Note on text size:** There is no hard character limit per text entry, but texts longer than approximately 50,000 characters may approach the default 120-second actor timeout. For very long documents, consider splitting them into logical sections (chapters, paragraphs, or pages) across multiple entries or runs.

---

### Example Input

**Single text analysis:**

```json
{
  "text": "The quick brown fox jumps over the lazy dog."
}
````

**Batch text analysis (multiple texts):**

```json
{
  "texts": [
    "The quick brown fox jumps over the lazy dog. This simple sentence contains every letter of the alphabet. It is often used for typing practice and font display.",
    "Despite the aforementioned complexities inherent in the implementation of multifaceted regulatory frameworks, it is incumbent upon stakeholders to ensure comprehensive compliance with all applicable statutory provisions and regulatory guidelines.",
    "Sign up now and get started in minutes. No credit card required. Join millions of satisfied users worldwide who trust our platform for their daily content needs."
  ]
}
```

**Batch analysis with language hint:**

```json
{
  "texts": [
    "The quick brown fox jumps over the lazy dog.",
    "Despite the aforementioned complexities inherent in the implementation of multifaceted regulatory frameworks, it is incumbent upon stakeholders to ensure comprehensive compliance."
  ],
  "language": "en"
}
```

***

### Output Structure

#### Field Reference

| Field | Type | Description |
|-------|------|-------------|
| `textPreview` | string | First 200 characters of the input text, with an ellipsis (`...`) appended if the original text exceeds 200 characters. Useful for identifying which text produced which result in batch outputs |
| `textLength` | integer | Total character count of the input text including spaces and all Unicode characters. Reflects the raw byte length of the input before any processing |
| `wordCount` | integer | Number of words detected using whitespace-delimited tokenization with punctuation stripped. Guaranteed to be at least 1 for non-empty texts to avoid division-by-zero in algorithm calculations |
| `sentenceCount` | integer | Number of sentences detected using sentence-ending punctuation (period, exclamation mark, question mark). Guaranteed to be at least 1 for non-empty texts |
| `characterCount` | integer | Count of alphanumeric characters only (`[a-zA-Z0-9]`). Excludes spaces, all punctuation, underscores, and special characters. This filtered count prevents the Coleman-Liau and ARI algorithms from being inflated by punctuation-heavy content |
| `avgWordLength` | float | Mean number of alphanumeric characters per word. Computed as `characterCount / wordCount`. Provides insight into vocabulary complexity at the character level |
| `avgSentenceLength` | float | Mean number of words per sentence. Computed as `wordCount / sentenceCount`. Higher values indicate longer, potentially more complex sentence structures |
| `fleschReadingEase` | object | Score (0–100), human-readable level classification, and intermediate counts. Contains sub-fields: `score` (float), `level` (string like "Standard (8th-9th grade)"), `sentences` (int), `words` (int), and `syllables` (int) |
| `fleschKincaidGrade` | object | Score (US grade level as float), grade label, and intermediate counts. Contains sub-fields: `score` (float), `gradeLevel` (string like "Grade 8" or "College+ (Grade 14)"), `sentences` (int), `words` (int), and `syllables` (int) |
| `gunningFog` | object | Score, grade label, complex word statistics, and intermediate counts. Contains sub-fields: `score` (float), `gradeLevel` (string), `complexWordCount` (integer), `complexWordPct` (float — percentage of words with 3+ syllables), `sentences` (int), and `words` (int) |
| `smogIndex` | object | Score and grade label. Contains sub-fields: `score` (float), `gradeLevel` (string), and `complexWordCount` (integer). Note: sentence count is clamped to a minimum of 30 for the SMOG formula |
| `colemanLiauIndex` | object | Score, grade label, and intermediate character/sentence statistics. Contains sub-fields: `score` (float), `gradeLevel` (string), `avgCharsPerWord` (float), and `avgSentencesPer100Words` (float) |
| `automatedReadabilityIndex` | object | Score, grade label, and character count. Contains sub-fields: `score` (float), `gradeLevel` (string), and `chars` (integer — same value as `characterCount`) |
| `overallGrade` | string | Composite A–F grade with description (e.g., `"A (Very Readable)"` or `"D (Difficult)"`). Computed by averaging normalized Flesch Reading Ease, Flesch-Kincaid Grade, Gunning Fog, and Coleman-Liau scores |
| `seoSuggestions` | array of strings | Contextual, actionable suggestions for improving readability. Each suggestion targets a specific issue: very difficult text, college+ grade level, high Gunning Fog Index, or overly simple content. Array may be empty if all scores are within optimal ranges |
| `language` | string | Echo of the `language` input parameter. Useful for downstream processing pipelines that need to track per-text language metadata |

#### Batch Output Fields

When the input contains multiple texts (via `texts` or a combination of `text` + `texts`), the output additionally includes:

| Field | Type | Description |
|-------|------|-------------|
| `results` | array of objects | Array of individual analysis result objects, one per input text. Each result has the full field set described above |
| `totalTexts` | integer | Total number of texts analyzed in the batch |
| `summary` | object | Batch summary containing `avgFleschReadingEase` (mean of all Flesch Reading Ease scores) and `avgGradeLevel` (mean of all Flesch-Kincaid Grade Level scores). Provides a quick overview of batch readability without inspecting every item |

***

### Output Format

#### Single Text Response

When a single text is provided (via the `text` field), the output is a single analysis object:

```json
{
  "textPreview": "The quick brown fox jumps over the lazy dog.",
  "textLength": 44,
  "wordCount": 9,
  "sentenceCount": 1,
  "characterCount": 35,
  "avgWordLength": 3.89,
  "avgSentenceLength": 9.0,
  "fleschReadingEase": {
    "score": 94.3,
    "level": "Very Easy (5th grade)",
    "sentences": 1,
    "words": 9,
    "syllables": 11
  },
  "fleschKincaidGrade": {
    "score": 2.3,
    "gradeLevel": "Grade 2",
    "sentences": 1,
    "words": 9,
    "syllables": 11
  },
  "gunningFog": {
    "score": 3.6,
    "gradeLevel": "Grade 3",
    "complexWordCount": 0,
    "complexWordPct": 0.0,
    "sentences": 1,
    "words": 9
  },
  "smogIndex": {
    "score": 3.1,
    "gradeLevel": "Grade 3",
    "complexWordCount": 0
  },
  "colemanLiauIndex": {
    "score": 3.8,
    "gradeLevel": "Grade 3",
    "avgCharsPerWord": 3.89,
    "avgSentencesPer100Words": 11.11
  },
  "automatedReadabilityIndex": {
    "score": 1.4,
    "gradeLevel": "Grade 1",
    "chars": 35
  },
  "overallGrade": "A (Very Readable)",
  "seoSuggestions": [],
  "language": "en"
}
```

#### Complex Text Response

Below is an example of a more complex text that triggers additional SEO suggestions and higher grade-level outputs:

```json
{
  "textPreview": "Despite the aforementioned complexities inherent in the implementation of multifaceted regulatory frameworks, it is incumbent upon stakeholders to ensure comprehensive compliance with all applicable s...",
  "textLength": 246,
  "wordCount": 29,
  "sentenceCount": 1,
  "characterCount": 216,
  "avgWordLength": 7.45,
  "avgSentenceLength": 29.0,
  "fleschReadingEase": {
    "score": 0,
    "level": "Very Confusing (College Graduate)",
    "sentences": 1,
    "words": 29,
    "syllables": 76
  },
  "fleschKincaidGrade": {
    "score": 26.6,
    "gradeLevel": "College+ (Grade 26)",
    "sentences": 1,
    "words": 29,
    "syllables": 76
  },
  "gunningFog": {
    "score": 32.3,
    "gradeLevel": "College+ (Grade 32)",
    "complexWordCount": 15,
    "complexWordPct": 51.7,
    "sentences": 1,
    "words": 29
  },
  "smogIndex": {
    "score": 7.2,
    "gradeLevel": "Grade 7",
    "complexWordCount": 15
  },
  "colemanLiauIndex": {
    "score": 27.0,
    "gradeLevel": "College+ (Grade 27)",
    "avgCharsPerWord": 7.45,
    "avgSentencesPer100Words": 3.45
  },
  "automatedReadabilityIndex": {
    "score": 28.2,
    "gradeLevel": "College+ (Grade 28)",
    "chars": 216
  },
  "overallGrade": "F (Very Difficult)",
  "seoSuggestions": [
    "Text is very difficult to read. Consider shorter sentences and simpler words.",
    "Grade level is college+. Consider simplifying for broader SEO reach.",
    "Gunning Fog index is high. Reduce complex words (3+ syllables) for better readability."
  ],
  "language": "en"
}
```

#### Batch Response

When multiple texts are provided (via the `texts` array), the output is wrapped in a batch envelope:

```json
{
  "results": [
    {
      "textPreview": "The quick brown fox jumps over the lazy dog. This simple sentence contains every letter of the alphabet. It is often used for typing practice and font display.",
      "textLength": 159,
      "wordCount": 28,
      "sentenceCount": 3,
      "overallGrade": "B (Readable)",
      "fleschReadingEase": { "score": 70.5, "level": "Fairly Easy (7th grade)" },
      "fleschKincaidGrade": { "score": 5.8, "gradeLevel": "Grade 5" },
      "gunningFog": { "score": 6.6, "gradeLevel": "Grade 6", "complexWordCount": 2 },
      "smogIndex": { "score": 4.6, "gradeLevel": "Grade 4", "complexWordCount": 2 },
      "colemanLiauIndex": { "score": 8.1, "gradeLevel": "Grade 8" },
      "automatedReadabilityIndex": { "score": 4.9, "gradeLevel": "Grade 4" },
      "seoSuggestions": [],
      "language": "en"
    },
    {
      "textPreview": "Despite the aforementioned complexities inherent in the implementation of multifaceted regulatory frameworks, it is incumbent upon stakeholders to ensure comprehensive compliance with all applicable s...",
      "textLength": 246,
      "wordCount": 29,
      "sentenceCount": 1,
      "overallGrade": "F (Very Difficult)",
      "fleschReadingEase": { "score": 0, "level": "Very Confusing (College Graduate)" },
      "fleschKincaidGrade": { "score": 26.6, "gradeLevel": "College+ (Grade 26)" },
      "gunningFog": { "score": 32.3, "gradeLevel": "College+ (Grade 32)", "complexWordCount": 15 },
      "smogIndex": { "score": 7.2, "gradeLevel": "Grade 7", "complexWordCount": 15 },
      "colemanLiauIndex": { "score": 27.0, "gradeLevel": "College+ (Grade 27)" },
      "automatedReadabilityIndex": { "score": 28.2, "gradeLevel": "College+ (Grade 28)" },
      "seoSuggestions": [
        "Text is very difficult to read. Consider shorter sentences and simpler words.",
        "Grade level is college+. Consider simplifying for broader SEO reach.",
        "Gunning Fog index is high. Reduce complex words (3+ syllables) for better readability."
      ],
      "language": "en"
    },
    {
      "textPreview": "Sign up now and get started in minutes. No credit card required. Join millions of satisfied users worldwide who trust our platform for your daily content needs.",
      "textLength": 160,
      "wordCount": 27,
      "sentenceCount": 3,
      "overallGrade": "B (Readable)",
      "fleschReadingEase": { "score": 81.8, "level": "Easy (6th grade)" },
      "fleschKincaidGrade": { "score": 4.1, "gradeLevel": "Grade 4" },
      "gunningFog": { "score": 3.6, "gradeLevel": "Grade 3", "complexWordCount": 0 },
      "smogIndex": { "score": 3.1, "gradeLevel": "Grade 3", "complexWordCount": 0 },
      "colemanLiauIndex": { "score": 9.4, "gradeLevel": "Grade 9" },
      "automatedReadabilityIndex": { "score": 5.9, "gradeLevel": "Grade 5" },
      "seoSuggestions": [],
      "language": "en"
    }
  ],
  "totalTexts": 3,
  "summary": {
    "avgFleschReadingEase": 50.8,
    "avgGradeLevel": 12.2
  }
}
```

***

### Technical Notes

#### Syllable Counting

The actor uses a heuristic-based English syllable counter that applies the following deterministic rules in sequence:

1. **Punctuation stripping**: All punctuation characters (non-word, non-space, non-apostrophe characters) are removed from the word before analysis. This ensures that punctuation does not artificially inflate character-group counts.

2. **Silent 'e' removal**: Words ending in a silent 'e' that are longer than 2 characters have the trailing 'e' removed before vowel-group counting. This prevents the common English pattern of a silent final 'e' from being counted as an additional syllable (e.g., "make" → "mak" → 1 syllable, not 2).

3. **Syllabic '-le' handling**: Words ending in '-le' that are longer than 3 characters (e.g., "table", "little", "candle") get an appended 'a' to capture the syllabic 'le' sound as a distinct vowel group. Without this rule, the syllabic consonant in words like "little" would be counted as 1 syllable instead of the correct 2.

4. **Vowel group counting**: Consecutive vowel characters (`[aeiouy]+`) are grouped together and each group is counted as one syllable. This handles diphthongs (e.g., "ou" in "cloud"), triphthongs (e.g., "iou" in "various"), and consecutive vowels correctly — they produce a single syllable count regardless of how many vowel letters appear in sequence.

5. **Silent ending reduction**: Words ending in common silent suffixes (`-ed`, `-es`, `-ely`) have their syllable count reduced by one when the count exceeds 1. This corrects for past tense and adverb endings that add letters but not syllables in standard English pronunciation (e.g., "walked" → 1, not 2; "lively" → 2, not 3).

6. **Minimum syllable floor**: Every word is guaranteed at least one syllable (`max(1, count)`) regardless of its letter content. This prevents zero-syllable results for abbreviations, acronyms, or very short words like "a" and "I".

This heuristic is **tuned for standard English prose** and performs well on common vocabulary. It may consistently undercount or overcount on:

- **Technical jargon** — domain-specific terms with unusual vowel patterns (e.g., "nanotechnology", "electroencephalography")
- **Neologisms** — newly coined words, brand names, and portmanteaus (e.g., "cryptocurrency", "fintech")
- **Loanwords** — words adopted from other languages that retain non-English pronunciation patterns (e.g., "naïve", "résumé", "voilà")
- **Non-English text** — all algorithms assume English-language phonetic patterns; non-English text will produce unreliable syllable and readability scores

#### Algorithm Edge Cases

- **SMOG Index Clamping**: The SMOG formula is statistically designed for samples of approximately 30 sentences. The implementation clamps `sentenceCount` to a minimum of 30 using `max(sentences, 30)` to prevent unrealistically low scores on very short texts. This means that for texts with fewer than 30 sentences, the SMOG score should be interpreted as **approximate** rather than definitive — it reflects the expected score if the text were extrapolated to 30 sentences. For best results with SMOG, provide texts of at least 30 sentences when precise scores are needed.

- **Grade Labeling for Scores Above 20**: Scores that produce a grade level of 20 or higher are labeled `"College+ (Grade N)"` (e.g., `"College+ (Grade 21)"`) to indicate that the text demands post-secondary reading proficiency beyond typical undergraduate level. The numeric score remains accurate, but the grade label shifts from specific grade numbers to the college-plus category.

- **Zero-Length and Whitespace-Only Inputs**: Empty strings and whitespace-only texts return a structured error object with zeroed counts (`wordCount: 0`, `characterCount: 0`, `sentenceCount: 0`) and an `"error"` field containing `"Empty text provided"` instead of causing an unhandled exception. This allows batch runs to continue uninterrupted when encountering blank or malformed entries. The batch response will include error entries alongside valid analysis results.

- **Character Counting Methodology**: The `characterCount` field counts only alphanumeric characters (`[a-zA-Z0-9]`), explicitly excluding underscores and all punctuation. This filtered character count prevents the Coleman-Liau Index and Automated Readability Index from being inflated by punctuation-heavy content (e.g., lists, code snippets, or texts with many quotation marks) that would artificially increase the character-per-word ratio while not reflecting actual reading difficulty.

- **Edge Case — Single-Word Inputs**: Very short inputs consisting of a single word (e.g., "Hello") produce valid scores but should be interpreted with caution. Sentence-count-based algorithms (Flesch-Kincaid, Gunning Fog) may produce inflated or deflated results because the sentence/word ratio assumptions embedded in the formulas break down at the single-sentence or single-word extremes.

- **Edge Case — All-Caps or Mixed Case**: Readability algorithms operate on word length and character composition, not case. All-caps text, title case, or mixed case does not affect scores directly, but all-caps may indicate emphasis that a human reader would process differently — the algorithms are purely structural and do not account for typographic emphasis or formatting.

#### Performance

| Metric | Typical Value |
|--------|---------------|
| **Per-text execution time** | < 200 ms for most texts (up to ~5,000 characters) |
| **Memory footprint (single text)** | ~50–100 MB, dominated by the Python runtime and input string |
| **Memory footprint (batch of 100)** | ~100–300 MB, scaling sub-linearly due to shared runtime overhead |
| **Batch throughput (100 texts, ~500 chars each)** | 2–5 seconds total |
| **Maximum recommended text length** | No hard limit, but texts longer than ~50,000 characters may approach the 120-second actor timeout. Consider splitting very long documents (whole books, long research papers) into chapters, sections, or paragraphs across multiple runs |
| **Recommended actor memory allocation** | 512 MB (default). Sufficient for all standard use cases including full batches of 100 texts |
| **Scaling behavior** | CPU-bound for individual texts; I/O-bound only for input/output serialization. Performance scales linearly with total characters processed across all texts in a batch |

For production deployments with predictable throughput requirements, a batch of 100 texts of average length (~500 characters each) requires approximately 2–5 seconds of execution time and under 512 MB of memory. Throughput scales roughly as `O(total_characters)` across the batch, so doubling the total character count doubles the expected execution time.

***

### Use Cases

- **SEO Content Optimization** — Analyze blog posts, landing pages, and marketing copy against target audience reading levels. Content written at a 7th–8th grade level consistently outperforms college-level content in search engagement metrics including time on page, bounce rate, and conversion rate. Use the Flesch-Kincaid Grade Level and Gunning Fog Index to validate every draft before publishing, and let the contextual SEO suggestions guide targeted rewrites for underperforming pages. For competitive analysis, batch-score your top 10 competitors' homepage copy to benchmark your industry's average readability and identify opportunities to differentiate by simplifying.

- **Editorial Quality Control and Publishing Pipelines** — Integrate the actor into your editorial workflow as an automated pre-publication quality gate. Define a minimum readability threshold appropriate for your audience (e.g., Flesch Reading Ease ≥ 60 and grade level ≤ 9 for general consumer content) and reject or flag drafts that fall outside the acceptable range. For content management systems with API access, the actor can be called programmatically before every publish action, creating a hard or soft gate that prevents complexity drift over time. Batch-score every article in your editorial calendar quarterly to catch systemic readability changes introduced by new writers or shifting editorial direction.

- **Technical Documentation Audits** — Developer documentation, API references, and knowledge-base articles are notoriously prone to complexity creep as teams add detail, edge cases, and advanced examples over time. Run a batch analysis across your entire documentation tree — README files, getting-started guides, API tutorials, troubleshooting guides, and changelogs — to identify sections where the Gunning Fog Index exceeds 14 or the SMOG Index suggests college-level reading demands. Prioritize rewrites for sections that flatten the complexity curve, making documentation more accessible to junior developers, non-native-English-speaking users, and customers evaluating your product for the first time.

- **Educational Materials Validation** — Textbook authors, curriculum designers, and e-learning content creators can validate that reading materials match their intended student grade level with objective, reproducible metrics. Submit textbook chapters, worksheets, assessment prompts, and supplementary reading materials to confirm that Coleman-Liau and ARI scores align with the target grade. Flag materials that score significantly above the target grade level for differentiation or scaffolding support, and flag materials that score below grade level for enrichment or extension activities. This is especially valuable for multi-grade curriculum series where consistency across grade levels is critical.

- **Accessibility and Plain Language Compliance** — Government agencies, healthcare organizations, and financial institutions increasingly face enforceable plain-language mandates including the US Plain Writing Act of 2010, UK National Health Service content standards requiring readability at or below age 9, EU Web Accessibility Directive (EN 301 549), and healthcare-specific literacy guidelines such as the NIH Plain Language Guidelines. The SMOG Index — originally developed specifically for healthcare literacy assessment — is the standard metric for medical and health-related content. Batch-analyze patient information leaflets, informed consent forms, terms of service agreements, privacy policies, public-facing regulatory documents, and financial disclosure statements to produce objective, auditable compliance evidence for regulatory submissions or accessibility audits.

- **UX Writing and Product Copy Review** — Error messages, onboarding tooltips, empty-state copy, push notifications, confirmation dialogs, and in-app microcopy directly impact user experience, task completion rates, and conversion. Submit interface copy to verify that Flesch Reading Ease scores stay above 70 (Fairly Easy or better) for general-audience consumer products, or tune for professional SaaS tools (50–69, Standard to Fairly Difficult). The short-text-friendly nature of the character-based algorithms (Coleman-Liau, ARI) makes them particularly reliable for microcopy analysis where the limited word count makes syllable-based algorithms unstable. Combine the numerical scores with the SEO suggestions to get specific guidance on which UI text elements need rewriting.

- **Academic Research in Linguistics and Discourse Analysis** — Researchers studying text complexity, corpus linguistics, discourse analysis, genre comparison, or diachronic language change can use the actor's reproducible multi-algorithm pipeline for consistent, auditable scoring across large text corpora. The intermediate statistics — word counts, sentence lengths, character densities, complex word percentages — provide granular data suitable for regression analysis, factor analysis, or machine learning feature engineering in natural language processing pipelines. Because all six algorithms are computed from the same text using the same syllable counter, results are reproducible across runs and researchers, eliminating the variability introduced by running different texts through different standalone tools.

- **AI Training Data Quality Assessment** — When curating or evaluating training datasets for large language models — particularly for instruction tuning, summarization, or dialogue datasets — use the actor to assess the readability profile of your training corpus. High variance in readability across training examples can produce inconsistent model outputs; low-variance readability may limit the model's ability to handle diverse input complexity. Batch-score your entire dataset to compute per-text and aggregate readability metrics, identify outlier texts that are significantly more complex or simpler than the dataset mean, and curate a balanced training corpus with controlled readability distribution. This is especially relevant for domain-specific models (legal, medical, educational) where the training data's readability should match the target deployment audience.

***

# Actor input Schema

## `texts` (type: `array`):

Array of text strings to analyze for readability. Each text is scored independently. Max 100 texts per run.

## `text` (type: `string`):

A single text string to analyze. Alternative to 'texts' array.

## `language` (type: `string`):

Language of the text (default: 'en'). Affects syllable counting for English texts.

## Actor input object example

```json
{
  "texts": [
    "The quick brown fox jumps over the lazy dog. This simple sentence contains every letter of the alphabet.",
    "Despite the aforementioned complexities inherent in the implementation of multifaceted regulatory frameworks, it is incumbent upon stakeholders to ensure comprehensive compliance."
  ],
  "text": "The quick brown fox jumps over the lazy dog.",
  "language": "en"
}
```

# Actor output Schema

## `results` (type: `string`):

Text readability analysis results in the default dataset — one item per analysis

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "texts": [
        "The quick brown fox jumps over the lazy dog. This simple sentence contains every letter of the alphabet.",
        "Despite the aforementioned complexities inherent in the implementation of multifaceted regulatory frameworks, it is incumbent upon stakeholders to ensure comprehensive compliance."
    ],
    "text": "The quick brown fox jumps over the lazy dog.",
    "language": "en"
};

// Run the Actor and wait for it to finish
const run = await client.actor("perryay/content-readability-analyzer").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "texts": [
        "The quick brown fox jumps over the lazy dog. This simple sentence contains every letter of the alphabet.",
        "Despite the aforementioned complexities inherent in the implementation of multifaceted regulatory frameworks, it is incumbent upon stakeholders to ensure comprehensive compliance.",
    ],
    "text": "The quick brown fox jumps over the lazy dog.",
    "language": "en",
}

# Run the Actor and wait for it to finish
run = client.actor("perryay/content-readability-analyzer").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "texts": [
    "The quick brown fox jumps over the lazy dog. This simple sentence contains every letter of the alphabet.",
    "Despite the aforementioned complexities inherent in the implementation of multifaceted regulatory frameworks, it is incumbent upon stakeholders to ensure comprehensive compliance."
  ],
  "text": "The quick brown fox jumps over the lazy dog.",
  "language": "en"
}' |
apify call perryay/content-readability-analyzer --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=perryay/content-readability-analyzer",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Content Readability Analyzer — Flesch, Gunning Fog & SEO",
        "description": "Analyze text content with Flesch-Kincaid, Gunning Fog, SMOG, Coleman-Liau, and Automated Readability Index. Get grade levels, reading ease scores, and SEO-friendly suggestions for content optimization.",
        "version": "1.0",
        "x-build-id": "1EYeorqjeP7ic38cN"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/perryay~content-readability-analyzer/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-perryay-content-readability-analyzer",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/perryay~content-readability-analyzer/runs": {
            "post": {
                "operationId": "runs-sync-perryay-content-readability-analyzer",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/perryay~content-readability-analyzer/run-sync": {
            "post": {
                "operationId": "run-sync-perryay-content-readability-analyzer",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "texts": {
                        "title": "Texts to Analyze",
                        "type": "array",
                        "description": "Array of text strings to analyze for readability. Each text is scored independently. Max 100 texts per run.",
                        "default": []
                    },
                    "text": {
                        "title": "Single Text (alternative to texts array)",
                        "type": "string",
                        "description": "A single text string to analyze. Alternative to 'texts' array."
                    },
                    "language": {
                        "title": "Language",
                        "type": "string",
                        "description": "Language of the text (default: 'en'). Affects syllable counting for English texts.",
                        "default": "en"
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
