A rewritten Google Translate client for Node.js, with one dependency and typed errors
🈯 A Node.js library to consume Google Translate API for free.
At a glance
- What is it?
- The @iamtraction/google-translate package calls the free Google Translate endpoint and returns a structured object describing the translation, the detected source language and any correction the service applied. Version 3 is a rewrite of an older library, built on undici with hand written type declarations, a request shape you can inspect, and errors that carry a name and an HTTP style code.
- Who is it for?
- Adopt this package if you need translation in a Node.js service and a free endpoint is acceptable, since the API is small, the dependency footprint is one package, and the response tells you what the service detected and corrected. Do not adopt it for a commercial product that needs a service level agreement, because the endpoint is the free web one with no contract behind it.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 3 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The response tells you what the service detected and what it fixed
The package is a Node.js library to consume Google Translate for free, and the feature highlights are automatically detect source language, automatic spelling corrections, automatic language correction, and being fast and reliable.
What makes the library more than a string in, string out wrapper is the shape of the response object. The translated text is under text, and the from field is an object describing what the service made of your input. Inside it, from.language.iso is the code of the language recognised in the text, and from.language.didYouMean is a boolean saying whether the API suggested a correction in the source language.
Then there is the correction block, from.text, with three fields that describe what happened to your input. autoCorrected is true when the API has auto corrected the original text. didYouMean is true when it has suggested corrections. And value holds the corrected text or the text with suggested corrections, or an empty string unless autoCorrected or didYouMean is true.
The last field is raw, the raw response from the Google Translate servers, and it is an empty string unless options.raw is true.
So the caller can distinguish three cases that a plain string would collapse into one: the input was accepted unchanged, the input was silently corrected, or the input was accepted with a suggestion attached.
One function, five options, and a dispatcher you control
The entry point is a single method, translate(text, options), and it returns a Promise. The usage is a require and a call:
const translate = require('@iamtraction/google-translate');translate(text, options).then(console.log).catch(console.error);The options table is where the behaviour is decided. The text parameter is required and is what you want translated. The options object carries from and to, both optional: from defaults to auto, so the source language is detected when you do not name it, and to defaults to en, so an unconfigured call translates into English. Both accept a language name or a code.
The other three options are the interesting ones for production use. raw, defaulting to false, makes the call return the raw output received from Google Translate, which is what you want when you are debugging a parsing problem. dispatcher takes an undici dispatcher, which is the object that decides how the HTTP request is made.
That last option connects to the proxy story. Behind a proxy you set HTTP_PROXY, HTTPS_PROXY and NO_PROXY in the environment, and the library picks that up. If you want to take over entirely you pass options.dispatcher yourself. Without either, undici's global dispatcher is used, which is the default path.
The dependency list matches: undici is the only runtime dependency, at version 8.10.0 or newer.
Language lookup has helpers, and the table stays clean when you iterate it
The language table is exposed as translate.languages, keyed by code, with two helpers attached:
translate.languages['pa-Arab']; // OUTPUT: Punjabi (Shahmukhi)
translate.languages.getCode('Spanish'); // OUTPUT: es
translate.languages.isSupported('klingon'); // OUTPUT: falsegetCode accepts a code or a display name, case insensitively, and returns the code in its canonical casing, or null if the language is not supported. isSupported answers the same question as a boolean.
One implementation detail is worth knowing if you plan to iterate the table. The helpers are non-enumerable, so iterating the table yields only languages. That is a small thing, but it is the difference between a table you can loop over directly and one where you have to filter the helper keys out, and it is the kind of detail the readme bothers to state.
The first example also shows that the table is not a flat two letter list. The key pa-Arab is a language code with a script subtag, and the value is the display name Punjabi (Shahmukhi), which means the table distinguishes scripts where that matters.
Errors are thrown before the request, or carry the upstream status
The error handling is the part of the readme that a reviewer should read twice, because it changes how you write the calling code.
Rejections carry a name to tell them apart, and a code with HTTP semantics. The first case is UnsupportedLanguageError with a code of 400, thrown when options.from or options.to is not a supported language, and no request is made at all. The second is TranslateResponseError with the response status as the code, thrown when Google Translate answered with a status other than 200. The third is TranslateResponseError with a code of 502, thrown when Google Translate answered 200 with a body that could not be parsed, in which case the original parse error is on err.cause.
The guidance that follows is a design decision worth copying: match on name rather than code, as an upstream rejection also reports 400. So the 400 on UnsupportedLanguageError and a 400 coming back from the service are indistinguishable by code, and the name is the only reliable discriminator.
The example shows the shape of the handling:
translate('Tu es incroyable!', { to: 'klingon' }).catch(err => {
if (err.name === 'UnsupportedLanguageError') console.error(err.message);
});Note that this call never leaves your machine, because the language check happens before the request.
The tests are mostly offline, and one file talks to Google
The development section describes a test setup that is unusually deliberate for a library this small, and it is worth understanding before you trust a green run.
Most of the suite runs offline. The languages, request, parse and errors suites mock the transport through the public dispatcher option, so they assert what this library does, the request it builds, how it parses the response, and how it validates and reports errors, without a network call. Only test/smoke.test.js reaches the real translate.google.com, and a red run there may be Google rate limiting rather than a regression. That test checks only that a live response still parses into the expected shape, because whether a translation is correct is Google's concern rather than this library's, so no test asserts translated content.
That is a well-chosen boundary. A translation library that asserted specific translated strings would fail whenever Google changed its behaviour, and the tests here are built to survive that while still catching a genuine regression in the request or the parse.
The commands are three, and the readme points out a trap:
npm run lint # ESLint
npm test # the test suite
npm run test:coverage # the test suite with a coverage report for src/Lint is separate from tests and is not run by npm test, CI runs it as its own step, and a habit of running npm test alone will skip it.
To run just the offline suites, the readme gives the explicit file list: node --test test/languages.test.js test/request.test.js test/parse.test.js test/errors.test.js.
The package itself is commonjs with main at src/index.js, and it ships hand written type declarations at typings/index.d.ts, with the exports map pointing types at that file.
Why the rewrite happened, and where the free endpoint is the real risk
The credits section explains the history. The original version of the library was written by matheuss, and the current author rewrote it, with improvements and without using many external libraries, as the original library was not actively developed and had vulnerabilities.
That rewrite is visible in the repository. The version history shows v2.0.0 and v2.0.1 in 2022, then a gap of nearly four years and v3.0.0 on 2026-08-05, with the last push on 2026-10-19. The dependency count is the clearest evidence of the rewrite: one runtime dependency, undici, where the previous generation of these clients typically pulled in a request library, a parser and a language list.
The licensing is MIT, with a LICENSE file at the root.
The real limitation is not technical, it is legal and operational. This library talks to the endpoint the free web interface uses, and there is no agreement behind it. The readme's own framing, a library to consume Google Translate for free, is the point and the problem at once. A service that depends on it inherits the possibility that the endpoint changes shape, starts rate limiting more aggressively, or begins rejecting requests from your egress address. The smoke test in the repository exists precisely because that risk is real enough that a normal release process would not catch it before your users did.
The alternative to weigh is a paid translation API with a contract, a quota and a stability commitment. The difference in approach is that this library gives you a free call with no key and no terms, while a paid API gives you an SLA in exchange for a key, a rate limit you can plan around, and an invoice. For a hobby project, a personal tool, or a prototype that nobody depends on, the trade is clearly worth it. For a product, it is a decision to make deliberately rather than to inherit by accident.
One more operational detail deserves attention. The library defaults to translating into English, and the readme says the language table is the list of what is supported, which is a short and specific set rather than a general purpose list of every language Google can handle.
Editorial conclusion
Adopt this package if you need translation in a Node.js service and a free endpoint is acceptable, since the API is small, the dependency footprint is one package, and the response tells you what the service detected and corrected. Do not adopt it for a commercial product that needs a service level agreement, because the endpoint is the free web one with no contract behind it. Verify first that your Node.js runtime is 22.19.0 or later, that the language you need appears in translate.languages, and that you read the error handling in the readme before you rely on the response shape, because the errors are thrown before any request is made for an unsupported language.
Frequently asked questions
How do I install the @iamtraction/google-translate package?
Run npm install --save @iamtraction/google-translate for the stable version from npm, or npm install --save iamtraction/google-translate to get the latest version from GitHub. The package requires Node.js 22.19.0 or later.
How do I call the translate function in google-translate?
Require the package, then call translate(text, options), which returns a Promise. The from option defaults to auto for source detection and the to option defaults to en, and options.raw returns the raw response received from Google Translate.
How do I check whether a language is supported in @iamtraction/google-translate?
The language table is exposed as translate.languages, keyed by code, with getCode and isSupported helpers attached. getCode accepts a code or a display name case insensitively and returns the canonical code or null, and isSupported returns a boolean. The helpers are non-enumerable so iterating the table yields only languages.
How should I handle errors from the Google Translate client?
Match on the error name rather than the code, because an upstream rejection also reports 400. UnsupportedLanguageError with code 400 is thrown when a language is unsupported and no request is made, TranslateResponseError carries the response status for a non-200 answer, and TranslateResponseError with code 502 means a 200 body could not be parsed, with the original parse error on err.cause.
How do I use @iamtraction/google-translate behind a proxy?
Behind a proxy you set HTTP_PROXY, HTTPS_PROXY and NO_PROXY in the environment, and the library uses that. Passing options.dispatcher takes over entirely, and without either, undici's global dispatcher is used. The dispatcher option is also what the offline test suites use to mock the transport.
Official sources
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.
[](https://hysenlabs.com/projects/iamtraction-google-translate)Was this useful?