LLM Guides

How to Check Grammar and Spelling of Your Text Content with Python

Jul 08, 2026

Grammar and spelling checks are useful for blogs, support replies, product descriptions, emails, user-generated content, and AI-generated drafts.

If your app accepts text, you can use Python to catch basic mistakes before the text goes live. You can check typos, grammar issues, repeated words, punctuation problems, and style warnings. You can also return suggestions in JSON so your app can show corrections inside an editor.

In this guide, we’ll build a simple grammar and spelling checker with Python. We’ll start with language_tool_python, add a pure Python spell checker, and then show how to turn the checks into a small API.

Quick answer

The fastest way is to use LanguageTool through the Python wrapper language_tool_python. Its docs say the library can detect grammar errors and spelling mistakes from Python code or the command line.

Install it:

pip install language-tool-python

Then run:

import language_tool_python

tool = language_tool_python.LanguageTool("en-US")

text = "This are a simple sentence with a spelling mistke."

matches = tool.check(text)

for match in matches:
    print(match.message)
    print(match.replacements)

Example output:

The verb 'are' does not agree with the subject 'This'.
['is']

Possible spelling mistake found.
['mistake']

That gives you a practical grammar checker in a few minutes.

Why can we write this

We’ve spent around 6 years working with AI APIs, NLP workflows, text tools, and developer-focused automation. We also researched current Python grammar and spelling tools for this article, including LanguageTool, pyspellchecker, spaCy, and grammar correction research.

The simple version is: use LanguageTool for grammar and spelling suggestions, use a spell checker for lightweight typo checks, and add review logic before auto-fixing user text.

What can Python check?

A grammar checker can catch different types of issues.

Issue typeExamplePossible fix
Spellingmistkemistake
Subject-verb agreementThis are goodThis is good
Repeated wordsthe the textthe text
PunctuationLets goLet’s go
Capitalizationi am readyI am ready
Stylevery very goodvery good
Word confusiontheir going homethey’re going home

A basic spell checker works well for typos. Grammar needs more context, so a tool like LanguageTool is usually a better first choice.

Research on grammatical error correction also backs this up. The ERRANT paper introduced a toolkit for grammar error annotation and evaluation, which shows how grammar correction is usually measured by edit types rather than only “right or wrong.” In real apps, this means you want error categories, suggestions, and confidence, not just a red underline.

Option 1: Check grammar with LanguageTool

LanguageTool is one of the easiest options for Python grammar checks.

Install:

pip install language-tool-python

Basic code:

import language_tool_python

tool = language_tool_python.LanguageTool("en-US")

text = "She go to school every day. This sentence have a error."

matches = tool.check(text)

for match in matches:
    print("Issue:", match.message)
    print("Text:", text[match.offset:match.offset + match.errorLength])
    print("Suggestions:", match.replacements)
    print("Rule:", match.ruleId)
    print()

Example output:

Issue: The pronoun 'She' is usually used with a third-person or singular verb.
Text: go
Suggestions: ['goes']

Issue: The verb 'have' does not agree with the subject 'This sentence'.
Text: have
Suggestions: ['has']

This is already useful for an editor, CMS, chatbot, or content QA tool.

Return clean JSON

Most apps need structured output.

Here is a helper function:

import language_tool_python

tool = language_tool_python.LanguageTool("en-US")

def check_text(text):
    matches = tool.check(text)

    issues = []

    for match in matches:
        issues.append({
            "message": match.message,
            "error_text": text[match.offset:match.offset + match.errorLength],
            "offset": match.offset,
            "length": match.errorLength,
            "suggestions": match.replacements[:5],
            "rule_id": match.ruleId,
            "category": match.category
        })

    return {
        "text": text,
        "issue_count": len(issues),
        "issues": issues
    }

sample = "This are a test sentence with bad grammer."

print(check_text(sample))

Example output:

{
  "text": "This are a test sentence with bad grammer.",
  "issue_count": 2,
  "issues": [
    {
      "message": "The verb 'are' does not agree with the subject 'This'.",
      "error_text": "are",
      "offset": 5,
      "length": 3,
      "suggestions": ["is"],
      "rule_id": "THIS_NNS",
      "category": "GRAMMAR"
    },
    {
      "message": "Possible spelling mistake found.",
      "error_text": "grammer",
      "offset": 35,
      "length": 7,
      "suggestions": ["grammar"],
      "rule_id": "MORFOLOGIK_RULE_EN_US",
      "category": "TYPOS"
    }
  ]
}

This is the format you can send to a frontend.

Auto-correct text

LanguageTool can also apply suggestions.

import language_tool_python

tool = language_tool_python.LanguageTool("en-US")

text = "This are a test sentence with bad grammer."

matches = tool.check(text)
corrected = language_tool_python.utils.correct(text, matches)

print(corrected)

Output:

This is a test sentence with bad grammar.

Auto-correction is nice for drafts, but use it carefully. Some suggestions can change the meaning. For user-facing tools, it is often better to show suggestions and let the user accept them.

A 2024 study on grammar correction in Japanese learner writing found that one model had high adjusted precision but much lower recall after human review, meaning it was careful but missed many errors. The paper is about Japanese, but the lesson fits many grammar tools: grammar checks can help a lot, yet they still miss context-heavy mistakes. You can read the study here: Assessing the Efficacy of Grammar Error Correction.

Option 2: Check spelling with pyspellchecker

For simple spell checks, pyspellchecker is lightweight. Its docs say it uses Levenshtein distance to find likely corrections.

Install:

pip install pyspellchecker

Use it:

from spellchecker import SpellChecker

spell = SpellChecker()

text = "This sentense has a few speling mistakes."

words = text.split()
misspelled = spell.unknown(words)

for word in misspelled:
    print(word, "->", spell.correction(word))

Example output:

sentense -> sentence

speling -> spelling

You can also get multiple candidates:

print(spell.candidates(“speling”))

Example:

{‘spelling’, ‘spieling’}

This works well for fast typo checks, search boxes, small forms, and lightweight text QA.

When to use LanguageTool vs pyspellchecker

Here is the simple split.

NeedBetter choice
Grammar checksLanguageTool
Spelling checksLanguageTool or pyspellchecker
Pure Python typo detectionpyspellchecker
Style suggestionsLanguageTool
Multi-language grammarLanguageTool
App-level JSON issue outputLanguageTool
Very lightweight checkspyspellchecker

Use LanguageTool if you want a practical all-in-one grammar and spelling checker.

Use pyspellchecker if you only need typo detection and want a tiny setup.

Option 3: Add spaCy for text preprocessing

spaCy is not mainly a grammar checker, but it is useful around grammar workflows. Its docs explain that spaCy uses processing pipelines that tokenize text and add linguistic annotations. You can use it to split sentences, inspect tokens, find parts of speech, or prepare text before checking.

Install:

pip install spacy

python -m spacy download en_core_web_sm

Use it:

import spacy

nlp = spacy.load("en_core_web_sm")

text = "This are a sentence. It has two parts."

doc = nlp(text)

for sentence in doc.sents:
    print(sentence.text)

Output:

This are a sentence.

It has two parts.

This helps when you want to check long content sentence by sentence.

def split_sentences(text):

    doc = nlp(text)

    return [sent.text.strip() for sent in doc.sents]

print(split_sentences("This are wrong. This is fine."))

For large articles, checking one sentence or paragraph at a time can make results easier to show in an editor.

Build a full grammar check function

Here is a practical function that combines grammar checks with a clean score.

import language_tool_python

tool = language_tool_python.LanguageTool("en-US")

def grammar_report(text):
    matches = tool.check(text)

    issues = []

    for match in matches:
        issues.append({
            "message": match.message,
            "error_text": text[match.offset:match.offset + match.errorLength],
            "suggestions": match.replacements[:5],
            "category": match.category,
            "rule_id": match.ruleId,
            "offset": match.offset,
            "length": match.errorLength
        })

    word_count = len(text.split())
    issue_rate = len(issues) / max(word_count, 1)

    if issue_rate == 0:
        quality = "clean"
    elif issue_rate < 0.03:
        quality = "minor_issues"
    elif issue_rate < 0.08:
        quality = "needs_editing"
    else:
        quality = "needs_review"

    return {
        "word_count": word_count,
        "issue_count": len(issues),
        "issue_rate": round(issue_rate, 3),
        "quality": quality,
        "issues": issues
    }

text = """
This are a short paragraph with bad grammer.
It also have some spelling mistkes.
"""

print(grammar_report(text))

This gives your app a simple quality label:

QualityMeaning
cleanNo detected issues
minor_issuesA few small fixes
needs_editingSeveral issues
needs_reviewSend to editor or review flow

Build a Small API with FastAPI

If you want to check text from a web app, wrap the checker in an API.

Install:

pip install fastapi uvicorn language-tool-python

Create app.py:

from fastapi import FastAPI
from pydantic import BaseModel
import language_tool_python

app = FastAPI()
tool = language_tool_python.LanguageTool("en-US")

class TextRequest(BaseModel):
    text: str

@app.post("/check")
def check_grammar(request: TextRequest):
    text = request.text
    matches = tool.check(text)

    issues = []

    for match in matches:
        issues.append({
            "message": match.message,
            "error_text": text[match.offset:match.offset + match.errorLength],
            "suggestions": match.replacements[:5],
            "category": match.category,
            "offset": match.offset,
            "length": match.errorLength
        })

    return {
        "issue_count": len(issues),
        "issues": issues
    }

Run it:

uvicorn app:app –reload

Test it:

curl -X POST “http://127.0.0.1:8000/check” \

  -H “Content-Type: application/json” \

  -d ‘{“text”:”This are a bad sentence with a typoo.”}’

Example response:

{
  "issue_count": 2,
  "issues": [
    {
      "message": "The verb 'are' does not agree with the subject 'This'.",
      "error_text": "are",
      "suggestions": ["is"],
      "category": "GRAMMAR",
      "offset": 5,
      "length": 3
    },
    {
      "message": "Possible spelling mistake found.",
      "error_text": "typoo",
      "suggestions": ["typo"],
      "category": "TYPOS",
      "offset": 34,
      "length": 5
    }
  ]
}

Now you have a simple grammar checker API.

Add language support

LanguageTool supports many languages, so you can change the language code.

tool = language_tool_python.LanguageTool(“en-GB”)

Examples:

LanguageCode
American Englishen-US
British Englishen-GB
Germande-DE
Frenchfr
Spanishes
Ukrainianuk-UA

Always test with real text in that language. Grammar correction is harder across languages because each language has its own morphology, punctuation rules, and common learner errors.

A 2025 paper on multilingual grammatical error annotation makes this point well: grammar evaluation needs both language-agnostic structure and language-specific flexibility. In plain words, a grammar checker that works well for English may still need special rules for Korean, Ukrainian, German, or Romanian.

Should you auto-fix everything?

For simple typos, auto-fix can be fine.

For grammar, be more careful.

Issue typeAuto-fix?
Clear typoUsually safe
Repeated wordUsually safe
Missing periodUsually safe
Subject-verb agreementReview first
Word choiceReview first
Style suggestionReview first
Legal/medical/finance textHuman review

A grammar tool can suggest a technically valid fix that changes tone or meaning. For articles, emails, and product copy, show suggestions. For user-generated content, you can flag issues and let users accept fixes.

Use LLMs for style and rewrite suggestions

Grammar checkers are good for errors. LLMs are better for style, tone, clarity, and rewrites.

For example, LanguageTool can catch:

This are incorrect.

An LLM can help with:

Make this paragraph clearer and more casual.

A useful workflow:

  1. User text
  2. LanguageTool catches grammar and spelling issues
  3. Python returns issue list
  4. User accepts fixes
  5. LLM suggests optional rewrite
  6. Final text goes to editor/review

If you use LLMAPI, you can route basic rewrite tasks to a cheaper model and more complex editing tasks to a stronger model. You can also keep grammar checks separate from style rewrites, which makes the workflow easier to debug.

A practical content QA workflow

For blogs, landing pages, support replies, and AI-generated text, use a simple QA pipeline:

  1. Text draft
  2. Grammar and spelling check
  3. Style check
  4. Plagiarism/originality check if needed
  5. PII check if user data exists
  6. Human review
  7. Publish

For finance, legal, healthcare, or immigration content, keep a human in the loop. A grammar checker can catch surface errors, but it cannot confirm that the advice is correct.

Common mistakes

MistakeBetter approach
Auto-fixing every suggestionLet users review grammar and style fixes
Checking huge files at onceSplit by paragraph or section
Ignoring language variantUse en-US vs en-GB correctly
Using only a spell checkerAdd grammar checks too
Treating suggestions as perfectShow confidence and review options
Not storing offsetsKeep offsets so frontend can highlight issues
Checking only final textCheck drafts before publish
No test samplesTest with your real content

Full copy-paste example

Here is the complete version:

import language_tool_python

tool = language_tool_python.LanguageTool("en-US")

def check_text_quality(text):
    matches = tool.check(text)
    issues = []

    for match in matches:
        issues.append({
            "message": match.message,
            "error_text": text[match.offset:match.offset + match.errorLength],
            "suggestions": match.replacements[:5],
            "category": match.category,
            "rule_id": match.ruleId,
            "offset": match.offset,
            "length": match.errorLength
        })

    word_count = len(text.split())
    issue_rate = len(issues) / max(word_count, 1)

    if issue_rate == 0:
        quality = "clean"
    elif issue_rate < 0.03:
        quality = "minor_issues"
    elif issue_rate < 0.08:
        quality = "needs_editing"
    else:
        quality = "needs_review"

    corrected_text = language_tool_python.utils.correct(text, matches)

    return {
        "word_count": word_count,
        "issue_count": len(issues),
        "issue_rate": round(issue_rate, 3),
        "quality": quality,
        "issues": issues,
        "corrected_text": corrected_text
    }

if __name__ == "__main__":
    sample = """
    This are a short paragraph with bad grammer.
    It have several spelling mistkes.
    """

    report = check_text_quality(sample)
    print(report)

Final thoughts

You can check grammar and spelling in Python with a simple setup.

Use language_tool_python when you need grammar, spelling, punctuation, and style suggestions. Use pyspellchecker when you only need lightweight typo detection. Add spaCy if you want sentence splitting, tokenization, and better preprocessing for longer content.

For real apps, return structured JSON with issue messages, offsets, categories, and suggestions. Let users review fixes before you apply them. If you need rewriting, tone changes, or content polishing, add an LLM step after the grammar check.

For a larger text workflow, use LLMAPI to route grammar-adjacent tasks like rewriting, summarization, tone checks, and content QA across different models without rebuilding the whole pipeline every time.

Deploy in minutes