Breaking Free: How to Fix LanguageTool's Overleaf Block (A Technical Deep-Dive)
LanguageTool started blocking Overleaf with a "temporarily disabled" message. We reverse-engineered the extension, found the culprit, and created a client-side patch that bypasses the restriction entirely. Here's how we did it and how you can fix it too.
When your favorite grammar checker decides to ghost your favorite LaTeX editor 📝
TL;DR
LanguageTool started blocking Overleaf with a "temporarily disabled" message. We reverse-engineered the extension, found the culprit, and created a client-side patch that bypasses the restriction entirely. Here's how we did it and how you can fix it too.
The problem: When extensions go rogue
If you're a LaTeX user who relies on LanguageTool for grammar checking, you've probably hit this frustrating wall:
Lo sentimos, LanguageTool ha deshabilitado temporalmente el soporte
para este sitio web. Estamos trabajando en una solución.
Debería ser cuestión de días.
Translation: "Sorry, LanguageTool has temporarily disabled support for this website. We're working on a solution. It should be a matter of days."

The Investigation: Going Down the Rabbit Hole
Step 0: Asking for support
As a LanguageTool user and suscriber I have access to the support team. I reached them with some screenshoots and, after some interactions, they replied me that they were aware of the issue and the haven't had and ETA.
The offered me a reimbursement, but I'd like to keep using Language Tool, as I found it really useful!
Step 1: Finding the Smoking Gun
First, I dug into the extension's localization files to trace where this message comes from. In _locales/es/messages.json, there it was:
{
"siteTemporarilyUnsupported": {
"message": "Lo sentimos, LanguageTool ha deshabilitado temporalmente..."
}
}
The message key siteTemporarilyUnsupported was our first clue.
Step 2: Following the Breadcrumbs
Using grep to search through the minified JavaScript files, I found this logic in popup.js:
ff.isDomainSupported(Z_) ?
ff.isDomainExcludedByGroupPolicy(Z_) && (d.supported=!1, d.unsupportedMessage=In.getMessage("siteDisabledPerGroupPolicy")) :
(d.supported=!1, d.unsupportedMessage=In.getMessage("siteTemporarilyUnsupported"))
Bingo! When isDomainSupported() returns false, it triggers our dreaded error message.
Step 3: The Remote Config Revelation
Digging deeper, I discovered that LanguageTool uses a remote configuration system. The extension fetches domain blacklists from:
https://languagetool.org/webextension_config.json
The isDomainSupported function checks against this dynamically updated list:
isDomainSupported(e) {
return !this._configuration ||
!this._configuration.unsupportedDomains.includes("*") &&
!Hr._isListContainsDomain(this._configuration.unsupportedDomains, e)
}
The thing here is that overleaf.com was not on this list! Only "seleniumbase.io" appears at the moment of writing.
Step 4: The Domain Matching Logic
The _isListContainsDomain function is particularly clever—it supports wildcard subdomain matching:
function Mt(e,t) {
const r = Ut(t); // Normalize domain
return (e||[]).some(e => {
const t = Ut(e);
return t === r || r.endsWith("." + t) // Exact OR subdomain match
});
}
This means if overleaf.com is blocked, so are www.overleaf.com, v2.overleaf.com, etc.
The Solution: Client-Side Liberation
The Strategy
Instead of trying to fight the remote configuration (which we can't control), we implement a client-side override. The beauty of browser extensions is that once you have the code, you can modify it.
The Implementation
The fix is elegantly simple. We modify the isDomainSupported function to always return true for Overleaf domains, regardless of what the remote config says:
isDomainSupported(e) {
// Always allow overleaf.com and its subdomains
if(e && (e.includes('overleaf.com') || e.endsWith('overleaf.com'))) {
return true;
}
// Original logic continues...
return !this._configuration ||
!this._configuration.unsupportedDomains.includes("*") &&
!Hr._isListContainsDomain(this._configuration.unsupportedDomains, e)
}
Files That Need Patching
LanguageTool's architecture spreads this function across multiple contexts:
background.js- Main extension logiccontent.js- Injected page scriptspopup.js- Extension popup interfacevalidator/validator.js- Grammar validation enginetoolbox/toolbox.js- Writing tools interfaceoptions/options.js- Settings management- And several others...
Each file contains its own minified version of the domain checking logic, so they all need the same patch.
Happy LaTeX writing, everyone! 🎉