One configuration that works end to end — the exact endpoint, the exact model, and the measurements behind the choice.
Google Translate works with no key at all, and if you only want to read the occasional page you can stop there. This guide is for the other case: you want translation good enough to read closely, plus the listening and speaking review that needs speech and transcription. That means bringing your own keys, and the whole point of doing so is that your text goes from your browser to that provider directly — there is no server of ours in between.
| Job | Engine | Model | Why |
|---|---|---|---|
| Translation | DeepSeek | deepseek-v4-flash | Paid, cheap, fast enough for whole pages |
| Read-aloud | Built-in device voice | — | Free, offline, no key |
| Transcription | OpenAI Transcribe | whisper-1 | Needed only for speaking review |
Install from the App Store, or load the Chrome or Firefox build. Then switch the extension on once — on iPhone that happens in Settings, and belliedmonkey.cc/setup.html detects it and confirms when it is actually working.
Sign up at https://platform.deepseek.com and create an API key. Any of the supported providers works; this guide uses DeepSeek because it is inexpensive, fast enough for whole pages, and its key works from anywhere.
Open the extension's Settings, choose DeepSeek as the translation engine, paste the key, and press Test connection. The endpoint and model are filled in for you — https://api.deepseek.com/v1/chat/completions with model deepseek-v4-flash — and you only change them if you are pointing at a gateway or a different model.
https://your-endpoint.example is not an endpoint, https://your-endpoint.example/v1/chat/completions is.The device's built-in voice is free, works offline and needs no key, which is the right default. If you want a better voice for listening practice, OpenAI Speech takes a key of its own at https://api.openai.com/v1/audio/speech with model gpt-4o-mini-tts.
Speaking review needs to hear you, which means a transcription endpoint. OpenAI Transcribe uses https://api.openai.com/v1/audio/transcriptions with model whisper-1 and the same kind of key. If you would rather nothing left your machine, point it at a local server instead — the field takes any endpoint speaking the same shape.
Open a page in a language you do not read, switch translation on, and check that each paragraph keeps its original with the translation underneath. If a paragraph fails it now says so with a retry you can press, rather than sitting at "Translating…".
Reasoning models are the trap here. Left alone, DeepSeek's deepseek-v4-flash spends tokens thinking about every single paragraph: measured on 2026-08-20, one paragraph took 3549 ms and burned 278 thinking tokens. With thinking switched off the same paragraph came back in 1126 ms — 3.2× faster for text that reads the same.
The extension sends that parameter for you, per host and per model, from a table built out of measurements rather than documentation. The reason it has to be measured is that documentation does not predict it: on another provider the identical situation cost 24833 ms before and 1410 ms after — 17.6× — and on a third, sending the documented parameter returns HTTP 200 with an empty body, which looks like a bug in the extension and is not.
A host the table has never seen gets the protocol minimum and nothing else, which is why a gateway inside your own company works on the first try instead of failing on a parameter it does not implement.
These are read from the same registry the software ships with, so this table cannot drift away from what the app actually does.
| Engine | Endpoint | Default model | Where to get a key |
|---|---|---|---|
| ChatGPT (OpenAI) | https://api.openai.com/v1/chat/completions | gpt-4o-mini | platform.openai.com/api-keys |
| Claude (Anthropic) | https://api.anthropic.com/v1/messages | claude-haiku-4-5-20251001 | console.anthropic.com |
| DeepSeek | https://api.deepseek.com/v1/chat/completions | deepseek-v4-flash | platform.deepseek.com |
| GLM (Z.ai) | https://api.z.ai/api/paas/v4/chat/completions | glm-4-flash | z.ai |
| Qwen | https://dashscope-intl.aliyuncs.com/compatible-mode/v1/chat/completions | qwen-plus | modelstudio.console.alibabacloud.com |
| Qwen MT | https://dashscope-intl.aliyuncs.com/compatible-mode/v1/chat/completions | qwen-mt-turbo | modelstudio.console.alibabacloud.com |
| Kimi | https://api.moonshot.ai/v1/chat/completions | kimi-k2.6 | platform.moonshot.ai |
Anything else that speaks one of the two request shapes works too — you supply the whole address yourself:
| Entry | Address shape | ||
|---|---|---|---|
| Custom (OpenAI-compatible) | https://your-endpoint.example/v1/chat/completions | — | — |
| Custom (Anthropic-compatible) | https://your-endpoint.example/v1/messages | — | — |
Several providers issue region-bound keys and run separate hosts for them, so a key from one console will not authenticate against the other's address. Check that the endpoint's domain matches the console you created the key in.
A request that returns HTTP 200 with an empty body is almost always a reasoning model that spent its whole output budget thinking. The extension avoids this for the models it knows; if you switched to a model by hand, switch back or reduce it to a non-reasoning one.
Settings live on the device and are not shared unless you turn sync on, so a key entered on a Mac is not on the phone. Enter it again there, or sign in and let sync carry it.
Not switched on yet? Start here →See also: frequently asked questions · YouTube dual subtitles · Safari on iPhone