language_tool_python: Python wrapper for LanguageTool
language_tool_python is a Python interface/wrapper to LanguageTool, an open-source grammar, style, and spell checker.
It can:
- run a local LanguageTool Java server,
- call LanguageTool public API,
- call your own remote LanguageTool server,
- be used from Python code and from a CLI.
Default local download target: LanguageTool 6.8.
Documentation
- Docs: https://language-tool-python.readthedocs.io/en/latest/
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
Requirements
- Python
>=3.9(tested up to 3.14) - Java (to run local LanguageTool server):
- LanguageTool
< 6.6: Java>=9 - LanguageTool
>= 6.6(default): Java>=17
- LanguageTool
Installation
pip install --upgrade language_tool_python
Quick Start
Local server
import language_tool_python
with language_tool_python.LanguageTool("en-US") as tool:
text = "A sentence with a error in the Hitchhiker's Guide tot he Galaxy"
matches = tool.check(text)
print(matches)
print(tool.correct(text))
Public LanguageTool API
import language_tool_python
with language_tool_python.LanguageToolPublicAPI("es") as tool:
matches = tool.check("Se a hecho un esfuerzo.")
print(matches)
Your own remote LanguageTool server
import language_tool_python
with language_tool_python.LanguageTool(
"en-US",
remote_server="https://your-lt-server.example.com",
) as tool:
print(tool.check("This are bad."))
Constructor Parameters Worth Knowing
language_tool_download_version (local server only)
Use this parameter to force which LanguageTool package is used when running a local server.
import language_tool_python
with language_tool_python.LanguageTool(
"en-US",
language_tool_download_version="6.7",
) as tool:
print(tool.check("This are bad."))
Accepted formats:
latest: latest snapshot available from the snapshot serverYYYYMMDD: snapshot by date (example:20260201)X.Y: release version (default:6.8. Examples:6.7,4.0)
Notes:
- Only relevant when using a local server (no
remote_server). - Versions below
4.0are not supported.
proxies (remote server only)
Use this parameter to pass proxy settings to requests when calling a remote LanguageTool server.
import language_tool_python
with language_tool_python.LanguageTool(
"en-US",
remote_server="https://your-lt-server.example.com",
proxies={
"http": "http://proxy.example.com:8080",
"https": "http://proxy.example.com:8080",
},
) as tool:
print(tool.check("This are bad."))
Notes:
proxiesworks only withremote_server.- Passing
proxieswithoutremote_serverraisesValueError.
Core Python API
Check text
matches = tool.check("This is noot okay.")
Each item is a Match object with these fields:
rule_idmessagereplacementsoffset_in_context,context,offset,error_lengthcategory,rule_issue_typesentence
Auto-correct
corrected = tool.correct("This is noot okay.")
# Uses first suggestion for each match
Apply only selected matches
text = "There is a bok on the table."
matches = tool.check(text)
# Keep a specific suggestion for first match
matches[0].select_replacement(2)
patched = language_tool_python.utils.correct(text, matches)
Check only parts matching a regex
matches = tool.check_matching_regions(
'He said "I has a problem" but she replied "It are fine".',
r'"[^"]*"',
)
Classify result quality
from language_tool_python.utils import classify_matches
status = classify_matches(tool.check("This is a cats."))
# TextStatus.CORRECT / TextStatus.FAULTY / TextStatus.GARBAGE
Rule and Language Controls
You can tune checks per instance:
tool.language = "en" # Can also be set from constructor (`LanguageTool("en")`)
tool.mother_tongue = "fr" # Can also be set from constructor (`LanguageTool("en", mother_tongue="fr")`)
tool.disabled_rules.update({"MORFOLOGIK_RULE_EN_US"})
tool.enabled_rules.update({"EN_A_VS_AN"})
tool.enabled_rules_only = False
tool.disabled_categories.update({"CASING"})
tool.enabled_categories.update({"GRAMMAR"})
tool.preferred_variants.update({"en-GB"})
tool.picky = True
Spellchecking control:
tool.disable_spellchecking()
tool.enable_spellchecking()
# Equivalent to:
tool.disabled_categories.update({"TYPOS"})
tool.disabled_categories.difference_update({"TYPOS"})
Custom Spellings
You can register domain-specific words:
with language_tool_python.LanguageTool(
"en-US",
new_spellings=["my_product_name", "my_team_term"],
new_spellings_persist=False,
) as tool:
print(tool.check("my_product_name is released"))
new_spellings_persist=True(default): keeps words in the local LT spelling file.new_spellings_persist=False: session-only, words are removed onclose().
Local Server Configuration (config=)
For local servers only, pass a config dictionary. Example:
with language_tool_python.LanguageTool(
"en-US",
config={
"cacheSize": 1000,
"pipelineCaching": True,
"maxTextLength": 50000,
},
) as tool:
print(tool.check("Text to inspect"))
Supported keys:
maxTextLength,maxTextHardLength,maxCheckTimeMillismaxErrorsPerWordRate,maxSpellingSuggestions,maxCheckThreadscacheSize,cacheTTLSecondsrequestLimit,requestLimitInBytes,timeoutRequestLimit,requestLimitPeriodInSecondslanguageModel,fasttextModel,fasttextBinarymaxWorkQueueSize,rulesFile,blockedReferrerspremiumOnly,disabledRuleIdspipelineCaching,maxPipelinePoolSize,pipelineExpireTimeInSeconds,pipelinePrewarmingtrustXForwardForHeader,suggestionsEnabled- spellcheck-only language keys:
lang-<code>lang-<code>-dictPath
Notes:
remote_serverandconfigcannot be used together.proxiescan only be used withremote_server.
CLI
Entry point:
language_tool_python [OPTIONS] FILE [FILE ...]
Use - as file to read from stdin.
Examples:
# Check a file
language_tool_python -l en-US README.md
# Check stdin
echo "This are bad." | language_tool_python -l en-US -
# Auto-apply suggestions
language_tool_python -l en-US --apply input.txt
# Use only selected rules
language_tool_python -l en-US --enabled-only --enable MORFOLOGIK_RULE_EN_US input.txt
# Use remote LT server
language_tool_python -l en-US --remote-host 127.0.0.1 --remote-port 8081 input.txt
Main options:
-l, --language CODE-m, --mother-tongue CODE-d, --disable RULES-e, --enable RULES--enabled-only-p, --picky-a, --apply-s, --spell-check-off--ignore-lines REGEX--remote-host HOST,--remote-port PORT-c, --encoding--verbose--version
Exit codes:
0: no issues2: issues found
Environment Variables
LTP_PATH: directory used to store downloaded LanguageTool packages.- default:
~/.cache/language_tool_python/
- default:
LTP_JAR_DIR_PATH: use an existing local LanguageTool directory (skip download).LTP_DOWNLOAD_HOST_SNAPSHOT: override snapshot download host.- default:
https://internal1.languagetool.org/snapshots/
- default:
LTP_DOWNLOAD_HOST_RELEASE: override release download host.- default:
https://languagetool.org/download/
- default:
LTP_DOWNLOAD_HOST_ARCHIVE: override archive download host.- default:
https://languagetool.org/download/archive/
- default:
LTP_DOWNLOAD_SHA256_<VERSION>: version-specific expected SHA-256 for the downloaded LanguageTool archive, for exampleLTP_DOWNLOAD_SHA256_6_9_SNAPSHOT.LTP_DOWNLOAD_SHA256: fallback expected SHA-256 for the downloaded LanguageTool archive.LTP_BYPASS_VERIFIED_DOWNLOADS: set totrueto skip SHA-256 verification.LTP_MAX_DOWNLOAD_BYTES: maximum downloaded ZIP size in bytes.- default:
536870912(512 MiB)
- default:
LTP_SAFE_ZIP_MAX_ARCHIVE_BYTES: maximum total compressed member size in bytes.- default:
536870912(512 MiB)
- default:
LTP_SAFE_ZIP_MAX_EXTRACTED_BYTES: maximum total extracted size in bytes.- default:
805306368(768 MiB)
- default:
LTP_SAFE_ZIP_MAX_MEMBERS: maximum ZIP member count.- default:
5000
- default:
LTP_SAFE_ZIP_MAX_MEMBER_EXTRACTED_BYTES: maximum extracted size for a single ZIP member in bytes.- default:
134217728(128 MiB)
- default:
LTP_SAFE_ZIP_MAX_MEMBER_COMPRESSION_RATIO: maximum compression ratio for a single ZIP member.- default:
100.0
- default:
LTP_SAFE_ZIP_MAX_TOTAL_COMPRESSION_RATIO: maximum compression ratio for the whole ZIP archive.- default:
10.0
- default:
Downloaded zips are verified with SHA-256 when a checksum is available. Checksums are resolved in this order:
LTP_DOWNLOAD_SHA256_<VERSION>, where non-alphanumeric characters in the version are replaced with_and the name is uppercased.LTP_DOWNLOAD_SHA256.- The bundled
language_tool_python/integrity.tomlmanifest.
The bundled manifest covers release/archive downloads. Snapshots are not stable, so provide LTP_DOWNLOAD_SHA256_<VERSION> or LTP_DOWNLOAD_SHA256 if you want to verify a snapshot. If no checksum is available, the download proceeds without SHA-256 verification.
Example:
export LTP_PATH=/path/to/cache
export LTP_JAR_DIR_PATH=/path/to/LanguageTool-6.8
export LTP_DOWNLOAD_SHA256_6_8=<sha256>
# export LTP_BYPASS_VERIFIED_DOWNLOADS=true
Resource Management
When using a local server, prefer a context manager or explicit close():
with language_tool_python.LanguageTool("en-US") as tool:
...
# or
tool = language_tool_python.LanguageTool("en-US")
...
tool.close()
Client/Server Pattern
You can run LT on one process/host and connect from another client:
# Server side
server_tool = language_tool_python.LanguageTool("en-US")
# Client side
client_tool = language_tool_python.LanguageTool(
"en-US",
remote_server=f"http://127.0.0.1:{server_tool.port}",
)
Error Types
Main exceptions in language_tool_python.exceptions:
LanguageToolErrorServerErrorJavaErrorPathErrorRateLimitError
Development
# Install dev dependencies
uv sync --group tests --group docs --group types
# Lint / format / types
uvx ruff@0.15.12 check .
uvx ruff@0.15.12 format .
uvx mypy@2.0.0
# Tests
pytest
License
GPL-3.0-only. See LICENSE.
Acknowledgements
This project is based on the original language-check project:
https://github.com/myint/language-check/
Metadata
Release files for language_tool_python 3.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| language_tool_python-3.4.0.tar.gz | 62.8 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| language_tool_python-3.4.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 126.0 kB
Release files / language_tool_python-3.4.0.tar.gz
| Download URL | language_tool_python-3.4.0.tar.gz |
|---|---|
| Size | 62.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8564d45970813bfc4c58c9d2d693571bb9678ebeef69ec5ef04ff1914053293d
|
|
BLAKE2b-256 checksum How to use checksums |
6bc7b02e31143e8bdf2c9d52f37f1a28ff721a2af9457b8d9f8b0fe328f4525f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.6.5
|
Release files / language_tool_python-3.4.0-py3-none-any.whl
| Download URL | language_tool_python-3.4.0-py3-none-any.whl |
|---|---|
| Size | 63.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
65a603e4d35e61a3a617d6dc9ad0ee1744c126aae93d602292eac57b83b8072e
|
|
BLAKE2b-256 checksum How to use checksums |
1c15495cc7417dc28de56b2fe45338a6442f9e6c5173a27758f29b8f009eb93d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.6.5
|
Security for language_tool_python 3.4.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.