DLX: a self-hosted translation API server in Go, and what the rename actually changed
DLX - Self-hosted translation API server. Unofficial; not affiliated with DeepL SE.
At a glance
- What is it?
- DLX exposes a DeepL-compatible HTTP endpoint on port 1188 from a single Go binary or container. It is a thin proxy, not a translation engine, and the README is explicit that it is not a DeepL product.
- Who is it for?
- DLX fits you if you already have a DeepL-compatible client and want the endpoint on your own host, on port 1188, with an optional TOKEN in front of it. Skip it if you need a translation engine of your own, offline operation, or a supported commercial contract, because DLX is a proxy in front of a third-party service and the README documents no fallback.
- 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 55 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 26, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem DLX solves, and who is actually asking
DLX is a proxy, not a translator. It accepts a POST to /translate, forwards the work to the DeepL service, and returns the result. Everything the project does sits in that hop: request shape, session handling, and a port number that DeepL-compatible clients already know how to talk to.
That matters because a number of tools (translation browser extensions, Bob plugins, and the wider category of clients that expect a DeepL-style endpoint) want a base URL and a key rather than a bespoke integration. If you run DLX on your own host, those clients point at http://your-host:1188 instead of at DeepL directly. The project's topics list bobplugin and deepl, which tells you where the original demand came from.
The audience is narrow and worth naming. It is people who already have a DeepL-compatible client and want the endpoint somewhere they control, and people who want one HTTP surface in front of translation for several tools rather than a key pasted into each one. It is not for anyone who wants translation to keep working when the upstream service does not, and it is not for anyone who needs a model they can run themselves. The README describes the project as a self-hosted translation API server written in Go, and that is the whole scope.
How the request flow works, from main.go to the upstream service
The repository layout is small enough to read in one sitting. main.go sits at the top level, with service/ and translate/ as the two working directories. The module is github.com/OwO-Network/DLX and go.mod pins go 1.25.0.
The HTTP layer is Gin, with gin-contrib/cors in the dependency list, so cross-origin requests are handled at the framework level rather than by hand. Outbound requests go through github.com/imroc/req/v3. Two dependencies are more interesting than the rest. github.com/refraction-networking/utls and github.com/quic-go/quic-go appear as indirect requirements, and github.com/andybalholm/brotli and github.com/klauspost/compress are present for compression. In practice that means the outbound leg is not a plain net/http POST: the stack carries TLS fingerprinting and HTTP/3 machinery, which is what you would reach for when a service is sensitive to client identity.
Response parsing uses github.com/tidwall/gjson, so the upstream body is read by path rather than unmarshalled into structs. That is a deliberate choice for a proxy: it tolerates fields the project does not model. It also means a shape change upstream surfaces as a missing gjson path, not a compile error, and nothing in the README describes what happens in that case.
The Dockerfile confirms the deployment shape. A golang:1.25 builder stage compiles with CGO_ENABLED=0 into a static binary named deeplx, and the runtime stage is alpine:latest running as a non-root deeplx user, with EXPOSE 1188 and ENTRYPOINT ["/app/deeplx"]. No configuration file is copied in, which is consistent with the README: there is no config file to speak of.
Installing DLX and sending a first translation
There are three documented paths: Docker, a prebuilt binary, and the compose file in the repository. The Docker path is the shortest. Note that the image names still say deeplx even though the repository was renamed to DLX, and the README says this is deliberate.
docker run -d -p 1188:1188 ghcr.io/owo-network/deeplx:latest
# or: docker run -d -p 1188:1188 missuo/deeplx:latestIf you prefer compose, the repository ships compose.yaml, and the README gives `docker compose up -d`. That file pins the image to ghcr.io/owo-network/deeplx:latest, sets restart: always, and maps 1188:1188. It also contains a commented-out environment block with TOKEN and DL_SESSION keys, which is the closest thing to configuration documentation the repository offers:
services:
deeplx:
image: ghcr.io/owo-network/deeplx:latest
restart: always
ports:
- "1188:1188"
# environment:
# - TOKEN=helloworld
# - DL_SESSION=xxxxxxFor the binary path, the README says to download the artifact for your platform from Releases and run it. Artifact names still use the deeplx_ prefix:
./deeplxOnce something is listening, the README's own example is the check to run. It posts a JSON body with text, source_lang and target_lang, and you should get a JSON response back rather than a connection error:
curl -X POST http://localhost:1188/translate \
-H "Content-Type: application/json" \
-d '{"text": "Hello, world!", "source_lang": "EN", "target_lang": "ZH"}'That is the entire documented surface. The README does not list other endpoints, health checks, metrics, or a way to inspect which upstream the process is talking to.
The rename, the trademark notice, and what still says deeplx
In July 2026 the project received a trademark notice forwarded by GitHub Trust & Safety, submitted on behalf of DeepL SE. The README's account is that the former name DeepLX contained the registered trademark DeepL and could suggest endorsement. The repository was renamed to DLX and DeepL branding was removed from the project.
The rename is cosmetic in the places that matter operationally. Docker Hub and GHCR image names remain deeplx, release artifact names remain deeplx_*, the binary the Dockerfile builds is still called deeplx, and the service files in the repository (deeplx.service, me.missuo.deeplx.plist) keep the old name too. So a deployment that follows the README will run a container called deeplx while the repository is called DLX, and any script that greps for one name will miss the other.
The legal position is stated plainly and repeatedly: DLX is not an official DeepL product, is not affiliated with, endorsed by or sponsored by DeepL SE, and DeepL is a registered trademark of DeepL SE. The MIT licence on this repository covers this project's code only. It does not grant anything with respect to DeepL's service, its terms, or its trademark, and it says nothing about whether the way DLX reaches the upstream service is permitted under whatever agreement governs your access. That is a question for your own counsel, not for the repository.
Where DLX is the wrong tool
The first limitation is structural: DLX does not translate. Every request depends on an upstream service that the project does not control. If that service is unreachable, rate-limits you, or changes its response shape, DLX has nothing to fall back on. The README documents no retry policy, no circuit breaker, no caching layer and no secondary provider. For a hobby endpoint behind a browser extension that is acceptable. For a pipeline where a failed translation breaks a build or a page render, it is not.
The second is the configuration surface. The README documents no environment variables at all. TOKEN and DL_SESSION appear only as commented lines inside compose.yaml, so the only evidence that they exist is a YAML comment. There is no documented behaviour for what happens when TOKEN is set but the client omits it, no rate limiting, and no described authentication scheme beyond that name. If you need per-user keys or quotas, you are reading service/ and translate/ yourself.
The third is operational visibility. The README does not document rollback, health endpoints, structured logs, or a graceful-shutdown story. Version tags are not described as immutable or as safe to pin, and compose.yaml references :latest, which means a restart can pull different code than the one you tested. The release history shows v1.2.2 on 2026-05-22, v1.2.3 on 2026-08-04 and v1.2.4 on 2026-08-06, so the recent cadence is uneven and the last push to the repository was on 2026-08-06. Nothing here is abandoned, but nothing about the release process is documented either.
The fourth is scope. If what you actually need is a translation model you host and run yourself, DLX is the wrong category of software entirely, and no amount of configuration will change that.
How DLX compares with calling DeepL directly or running LibreTranslate
The honest comparison is not DLX against another proxy. It is DLX against the two things it sits between.
Calling the DeepL API directly from each client is the baseline. You get one fewer process, one fewer port, and no proxy to keep current. What you lose is the single endpoint: every client holds its own credential and its own base URL, and any client that only speaks the DeepL shape has to be configured individually. DLX collapses that into one host and one port, and with TOKEN set it can put a single shared secret in front of the clients instead of distributing the upstream credential to each of them. That is the real trade: an extra hop and an extra thing to patch, in exchange for one place to point everything.
LibreTranslate is the other direction. It is a translation engine you run, so it keeps working when the network does and needs no upstream account. The cost is that it is a model with its own resource footprint and its own quality profile, and it does not answer the DeepL-compatible request shape that DLX's users are trying to satisfy. Choosing between them is choosing between a thin proxy in front of someone else's engine and a heavier service that is the engine. DLX's dependency list (utls, quic-go, brotli) is the fingerprint of the first choice; a model runtime would be the fingerprint of the second.
There is a third option worth stating: if your clients can be changed, a direct integration with whatever translation provider you already pay for removes DLX from the picture entirely. DLX earns its place when the clients cannot be changed and the endpoint must move.
Licence and the cost of keeping it running
The repository is MIT licensed, which is permissive and imposes no copyleft obligation on your own code. The Dockerfile builds a static binary and runs it as a non-root user in an alpine image, so the runtime footprint is small and there is no interpreter or package manager to keep patched inside the container beyond alpine itself. Upgrading means pulling a new image or replacing the binary; there are no migrations, no database and no state to preserve, because the project stores nothing.
The maintenance cost is not in the code, it is in the upstream. The dependency list includes uTLS and quic-go, which exist to make the outbound request look like a browser. That kind of compatibility work is inherently reactive: when the upstream service changes how it evaluates clients, the project has to change with it, and you have to pull the change. The README does not describe a compatibility policy, a supported upstream version, or a deprecation window, so the practical answer is that you track releases and test after each one.
On licensing, one boundary is worth stating without pretending to give legal advice: MIT covers the code in this repository. It does not cover DeepL's service, and the trademark notice described in the README shows that the naming question has already been raised once by the trademark holder. If you deploy DLX commercially, the terms that matter are the ones attached to your upstream access, not the MIT file.
Editorial conclusion
DLX fits you if you already have a DeepL-compatible client and want the endpoint on your own host, on port 1188, with an optional TOKEN in front of it. Skip it if you need a translation engine of your own, offline operation, or a supported commercial contract, because DLX is a proxy in front of a third-party service and the README documents no fallback. Before you deploy, check the image tag you pulled, whether TOKEN and DL_SESSION are set in your environment, and what your DeepL terms say about this kind of access.
Frequently asked questions
Is DLX an official DeepL product?
No. The README states that DLX is an independent open-source project, is not affiliated with, endorsed by or sponsored by DeepL SE, and that DeepL is a registered trademark of DeepL SE. The project was renamed from DeepLX to DLX in July 2026 after a trademark notice was forwarded by GitHub Trust & Safety.
Is there a free DeepL API key available?
The README does not describe obtaining or using an API key, and it documents no key-related environment variable. The only credential-shaped settings it hints at are TOKEN and DL_SESSION, which appear as commented-out lines in compose.yaml, and the README does not explain what either one does.
Which port does DLX listen on?
Port 1188. The README says the server exposes a simple HTTP API on port 1188, compose.yaml maps "1188:1188", and the Dockerfile ends with EXPOSE 1188.
Does DLX still use the deeplx name anywhere?
Yes. The README says the Docker Hub and GHCR image names remain deeplx and that release artifact names remain deeplx_*, and the Dockerfile builds a binary called deeplx. The repository also still contains deeplx.service and me.missuo.deeplx.plist.
Can DLX translate without an internet connection?
No. DLX is a proxy in front of the DeepL translation service, so translation depends on reaching that upstream service. The README documents no offline mode, no local model and no fallback provider.
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/owo-network-dlx)