CLI tool
jxmorris12/language_tool_python avatar
jxmorris12/language_tool_python

language_tool_python: a Python wrapper for the LanguageTool grammar checker

a free, non-AI python grammar checker 📝✅

533 stars72 forksPythonGPL-3.0

At a glance

What is it?
The package runs LanguageTool either as a local Java server, against the public API, or against your own remote instance, and returns match objects you can inspect and apply. It is a thin client, not a grammar engine, and that shapes both its fit and its limits.
Who is it for?
Adopt language_tool_python when you want LanguageTool's rules inside a Python pipeline and you can accept a Java runtime or a remote endpoint. Do not adopt it if you need a pure-Python dependency, a hosted SaaS with an SLA, or a checker whose rules you can audit line by line.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 4 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 7, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem language_tool_python solves for Python developers

LanguageTool itself is a Java application. Its rules, its language models and its HTTP server all live in that JVM process. If you write Python and want to check a sentence, your options without this package are to shell out to a jar, hand-roll HTTP calls against the public API, or reimplement the rule set, which nobody does. language_tool_python closes that gap. The README describes it as "a Python wrapper for LanguageTool, a free, multilingual, non-AI, open-source grammar, style, and spell checker", and the pyproject description is the shorter "Checks grammar using LanguageTool." The audience is narrow and clear: developers who already run Python and want grammar, style and spelling results as Python objects rather than as HTML from a web UI. The package does not add rules of its own. Every suggestion, message and replacement you see comes from LanguageTool. That distinction matters when you debug a false positive, because the fix usually lives upstream in the Java rule set, not in this repository.

Three backends and the match object they return

The wrapper supports three ways to reach LanguageTool, and the choice is the main architectural decision you make. The default constructor starts a local Java server, downloading LanguageTool 6.8 if it is not present. LanguageToolPublicAPI talks to the public LanguageTool endpoint, which requires no local Java but sends your text to a third party. Passing remote_server points at an instance you operate, for example behind a container. In all three cases the return type is the same list of match objects, and the README's quick start shows the shape: each match carries a message, a list of replacements, and an integer offset. The offset is the part that makes the wrapper useful in an editor or a diff tool, because you can map a suggestion back to a character range in the original string. The context manager form used throughout the examples is not decoration. A local server is a child process, and the with block is what shuts it down.

The public API path deserves a caveat the README does not spell out. Rate limits, availability and content policies belong to LanguageTool's hosted service, so a pipeline that works in a test can start failing in production for reasons that have nothing to do with this package.

Installing language_tool_python and running a first check

Installation is one pip command. The package requires Python 3.10 or newer, tested up to 3.15, and Java 17 or newer if you intend to run the local server.

bash
pip install --upgrade language_tool_python

The first check downloads and starts the local LanguageTool server, so expect a delay on the initial run. This example is taken from the README and returns two matches for the deliberately broken sentence.

python
import language_tool_python

with language_tool_python.LanguageTool("en-US") as tool:
    matches = tool.check("A sentence with a error in the Hitchhiker's Guide tot he Galaxy")

print(len(matches))
print(matches[0].message)
print(matches[0].replacements)
print(matches[0].offset)

The README states the output: a length of 2, the message 'Use "an" instead of "a" if the following word starts with a vowel sound', replacements ['an'], and offset 16. If you would rather not run Java locally, swap the class for LanguageToolPublicAPI with the same language tag. There is also a command line entry point, which is convenient for shell pipelines.

bash
echo "This are bad." | language_tool_python -l en-US -
language_tool_python -l en-US --apply input.txt

The first form reads from stdin, the second rewrites a file in place using the suggested corrections. For configuration options beyond the language tag and remote_server, the README defers to the Read the Docs site rather than listing them inline.

Where the wrapper stops being the right tool

The largest constraint is the Java dependency. A local server means a JVM, a downloaded LanguageTool distribution, and a process lifecycle to manage. In a slim container image or a serverless function with a tight cold-start budget, that is often a dealbreaker, and the public API is the only remaining option, which reintroduces the network and the third party. The second constraint is licence scope. The package is GPL-3.0-only, and LanguageTool itself is distributed under its own terms. If you are embedding this in a closed-source product, the GPL is a question for your own legal review, not something the README resolves. Third, the wrapper is only as good as the underlying rules. LanguageTool is rule-based and explicitly non-AI, so it will not catch a sentence that is grammatical but wrong in context, and it can flag constructions that are correct in your domain. Because the package exposes matches rather than a pass or fail verdict, you are expected to decide which ones to apply. The --apply flag on the CLI does not make that judgement for you; it applies what the rules returned.

How it compares with calling the LanguageTool API directly

The obvious alternative is skipping the wrapper and issuing HTTP requests to LanguageTool yourself, either the public endpoint or your own server. The difference is lifecycle management. Direct HTTP gives you full control over timeouts, retries, connection pooling and request batching, and it removes a dependency from your tree. What you give up is the local server handling: language_tool_python downloads LanguageTool, starts the Java process, waits for it to become ready, and shuts it down when the context manager exits. It also normalises the response into match objects with offsets and replacements, so you do not write that parsing layer. If your environment already runs a LanguageTool container and you only need one endpoint, the wrapper's local-server machinery is overhead you are paying for and not using. If you want a checker that runs entirely in Python with no JVM, this project is the wrong category of tool; that is a different class of library, not a configuration change. The repository also notes it is based on the earlier language-check project, which is where the API shape originally came from.

Maintenance, releases and upgrade cost

The repository is not archived, and the last push was on 2026-09-12. Releases are tagged on PyPI, the current version is 3.4.0 from 2026-05-14, and the same date carries LanguageTool-6.8 and LanguageTool-6.7 tags, which shows the bundled LanguageTool version is tracked separately from the wrapper version. The project follows Semantic Versioning, and the README states that deprecated APIs are removed at the next major version, so a major bump is where breakage will land. Upgrading LanguageTool itself is a second axis: a new rule set can change which matches your code receives even when the Python API is unchanged, so pinning matters more here than in a typical library. Development uses uv with a locked dependency set, and the Makefile exposes make install, make format, make check, make test and make doc. The check target runs ruff, mypy and zizmor, which tells you the project holds itself to linting, typing and workflow security checks. On licensing, the package is GPL-3.0-only per pyproject.toml and the LICENSE file; how that interacts with your distribution model is a question for a lawyer.

Editorial conclusion

Adopt language_tool_python when you want LanguageTool's rules inside a Python pipeline and you can accept a Java runtime or a remote endpoint. Do not adopt it if you need a pure-Python dependency, a hosted SaaS with an SLA, or a checker whose rules you can audit line by line. Verify first that Java 17 or newer is available where the code runs, that Python is 3.10 or newer, and which of the three backends (local, public API, remote server) fits your latency and privacy constraints.

Frequently asked questions

What is language_tool_python used for?

It wraps the LanguageTool grammar, style and spell checker so Python code can call it and receive match objects with messages, replacements and offsets. The README shows it used from a script and from the command line, against a local server, the public API or a remote server.

Is language_tool_python free to use?

The package is licensed GPL-3.0-only, and LanguageTool is described in the README as a free, open-source checker. The public API backend depends on LanguageTool's hosted service, whose terms are set by that service rather than by this repository.

How do I install language_tool_python?

Run pip install --upgrade language_tool_python. You need Python 3.10 or newer, and Java 17 or newer if you want the default local server, which downloads LanguageTool 6.8.

Is language_tool_python better than Grammarly?

The two are not comparable on the evidence here. Grammarly is a hosted commercial product, while language_tool_python is a client for the rule-based LanguageTool engine, which the README describes as non-AI. Which suits you depends on whether you need an embeddable library or a writing assistant.

Official sources

  1. Issues
  2. jxmorris12/language_tool_python on GitHub
  3. License: GPL-3.0
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/jxmorris12-language-tool-python.svg)](https://hysenlabs.com/projects/jxmorris12-language-tool-python)