fanzha-ai-proxy: an OpenAI-compatible gateway in front of the National Anti-Fraud AI assistant
国家反诈AI API 转 OpenAI 兼容格式反向代理服务 || 仅学习用途
At a glance
- What is it?
- The project wraps a Chinese anti-fraud chatbot behind /v1/chat/completions so existing OpenAI clients can talk to it. The hard part is not the proxy code, it is getting the JWT out of the phone app.
- Who is it for?
- Adopt it if you already hold a working Access Token and want the anti-fraud assistant reachable from an OpenAI-compatible client without writing your own adapter; the README's token extraction routes assume ADB or an intercepting proxy on a device you control. Do not adopt it if you need a documented licence, a published release, or a supported path to production, because none of those exist in the repository.
- Can I use it commercially?
- Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
- Is it still maintained?
- Yes. The repository last received commits 11 days ago.
- What is it written in?
- GitHub does not report a main language for this repository.
Answers come from the project's GitHub data, last synced on September 16, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
What fanzha-ai-proxy actually bridges
The National Anti-Fraud AI assistant speaks its own HTTP API, authenticated with a JWT. Every mainstream AI client, from NextChat to the OpenAI Python SDK, speaks /v1/chat/completions. fanzha-ai-proxy sits between the two and translates. The README describes it as a reverse proxy that converts the assistant into a standard OpenAI-compatible interface, and the repository is small: main.py, requirements.txt, .env.example, config.example.json, .gitignore, README.md. Nothing else. That smallness is the point. If you want the anti-fraud assistant available inside LobeChat or behind OneAPI, you either write this adapter yourself or you run this one. The audience is narrow and technical: someone who can connect a phone over ADB, run sqlite3 against an app database, and read a JSON blob for two token fields. The README states the project is for technical exchange, academic research and personal learning verification, and that it has no affiliation with the official application. Treat that as the scope boundary, not as boilerplate.
The request path from client to assistant and back
The service is FastAPI on top of httpx, per requirements.txt (fastapi>=0.100.0, uvicorn>=0.20.0, httpx>=0.24.0, python-dotenv>=1.0.0). A client posts to /v1/chat/completions with a model name and a messages array. The proxy resolves credentials in one of two ways: from the incoming Authorization: Bearer <token> header, or from the FANZHA_ACCESS_TOKEN environment variable when the header carries a placeholder. It then parses the messages structure, including nested array content, and forwards the request upstream to the assistant's backend. The README notes the upstream host as xzfzznt.gaj.sh.gov.cn in the packet-capture instructions. Responses come back in one of two shapes. Non-streaming returns a single completion object. Streaming returns SSE, and the README is specific about what was fixed: the first packet carries the role field, subsequent packets carry incremental deltas, and the stream closes with finish_reason: stop. That detail matters more than it sounds. Clients such as NextChat and the OpenAI SDK will hang or render nothing if the opening role chunk is missing or the terminal reason never arrives, so a proxy that gets this wrong is unusable even though it returns 200. On the credential side, the project implements an Access Token plus Refresh Token flow, and the README claims sessions can be maintained for roughly 90 days without a new login when the refresh token is configured. /v1/models is implemented as well, which is what lets a client populate its model dropdown instead of hardcoding a name.
Install and first call
The README requires Python 3.9 or newer. Clone the repository, install the four dependencies, and copy the environment template.
git clone https://github.com/Mai-xiyu/fanzha-ai-proxy.git
cd fanzha-ai-proxy
pip install -r requirements.txt
cp .env.example .envNote that the clone URL in the README points at Mai-xiyu/fanzha-ai-proxy while this repository is lfzk550/fanzha-ai-proxy. Check which fork you are pulling before you run anything.
Open .env and fill in the two token values. FANZHA_REFRESH_TOKEN is optional but is what enables the long-lived renewal described above.
FANZHA_ACCESS_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6...
FANZHA_REFRESH_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6...
HOST=127.0.0.1
PORT=8088
DEFAULT_MODEL=国家反诈AIStart the service with python main.py. The README states it listens on http://127.0.0.1:8088 by default. A first call looks like this:
curl http://127.0.0.1:8088/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer 你的Access_Token" \
-d '{
"model": "国家反诈AI",
"messages": [
{"role": "user", "content": "收到自称公检法的电话要求转账,应该怎么做?"}
],
"stream": true
}'With stream set to true you should see SSE chunks arrive progressively and terminate with finish_reason: stop. If the connection simply closes with no output, the token is the first thing to check, not the proxy. For SDK users, the same endpoint takes an OpenAI client with base_url set to http://127.0.0.1:8088/v1 and any non-empty api_key when the token is already configured server-side.
Getting the token is harder than running the server
This is where the project's real cost lives. The README gives three extraction methods and all three assume physical access to a device with the app installed and logged in. Method one, described as the most stable, requires developer options, USB debugging, and a rooted device: the database sits at /data/data/uni.app.UNIAD10B08/databases/DCStorage, and you copy it out with su -c, pull it, then query DC_AD10B08_storage for the key 'user' and parse accessToken and refreshToken out of the JSON. Method two avoids root by attaching Chrome DevTools to the app's Webview at chrome://inspect/#devices, watching the Network tab, sending a message in the app, and copying the Authorization header from a request to /api/ai/create_session or /api/ai/chat. Method three is an intercepting proxy pointed at xzfzznt.gaj.sh.gov.cn. None of these is a normal onboarding flow. If you cannot do any of them, the proxy is inert: it has no way to obtain credentials on its own. There is also a lifecycle problem the README does not resolve. Tokens expire, refresh tokens can be revoked, and the README does not document what the service does when renewal fails, whether it surfaces an error to the client or returns an empty completion. Plan on monitoring the upstream response yourself rather than trusting the proxy to tell you.
Where it fits badly
Do not use this as a general-purpose OpenAI gateway. It forwards to one upstream, for one assistant, with one credential model. There is no key pool, no per-user quota, no rate limiting, and no retry logic described in the README. If ten clients share one token, you have ten clients sharing one session and one expiry clock. The proxy also inherits the upstream's availability. When the assistant's backend is unreachable, the proxy has nothing to fall back on, and the README does not describe a timeout, circuit breaker or caching layer. There is a second, sharper limit: the repository has no declared licence. The README says the project is for technical exchange, academic research and personal learning verification, and that it is not affiliated with the official application, but a disclaimer is not a licence. Without one, the default position is that no rights are granted, which is a problem the moment you try to redistribute it or ship it inside a product. If your use case is a hosted service with an SLA, this is the wrong tool and no amount of configuration makes it the right one.
How it differs from LiteLLM and OneAPI
The natural comparison is a general OpenAI-compatible router such as LiteLLM or OneAPI. Those projects exist to fan one OpenAI-shaped request out across many providers, with key management, spend tracking, fallbacks and load balancing. fanzha-ai-proxy does the opposite: it takes one non-OpenAI upstream and makes it look like OpenAI. The direction of translation is reversed. That difference decides which you need. If you have five providers and want one endpoint, use a router. If you have one awkward upstream and want your existing client to reach it, a single-purpose adapter like this is less machinery than configuring a router to treat an unknown API as a custom provider. The README itself positions the project as something you plug into OneAPI or New API rather than replace them, which is the honest framing: it is a leaf adapter, not a hub. The trade-off is that a leaf adapter gets no benefit from the router ecosystem, so every capability you want (retries, quotas, logging) has to be added by you in main.py or in whatever sits in front.
Maintenance, licence and upgrade cost
The last push to this repository was on 2026-09-07, ten days before this writing, so the code is recent. There are no published releases, which means upgrades happen by pulling main. That is a real cost: no version numbers, no changelog, no way to pin a known-good state except by recording a commit hash yourself. The dependency set is small and unpinned at the patch level (fastapi>=0.100.0, uvicorn>=0.20.0, httpx>=0.24.0, python-dotenv>=1.0.0), so a fresh pip install can resolve to newer versions than the author ran. If you deploy this, pin the four packages in your own requirements file rather than relying on the ranges. On licensing, the repository carries no licence file, and the README's statement that the project is for learning and research is a scope note, not a grant of rights. Whether you can redistribute it, bundle it, or run it as part of a commercial service is a question for a lawyer, not for this article. The safest reading is that you have no explicit permission, and you should confirm the position with the maintainer before depending on it.
Editorial conclusion
Adopt it if you already hold a working Access Token and want the anti-fraud assistant reachable from an OpenAI-compatible client without writing your own adapter; the README's token extraction routes assume ADB or an intercepting proxy on a device you control. Do not adopt it if you need a documented licence, a published release, or a supported path to production, because none of those exist in the repository. Before wiring anything to it, verify that your token still resolves against xzfzznt.gaj.sh.gov.cn, that the model name you send matches DEFAULT_MODEL in .env.example, and that port 8088 is free.
Frequently asked questions
What does fanzha-ai-proxy do?
It is a reverse proxy that exposes the National Anti-Fraud AI assistant as an OpenAI-compatible API, implementing /v1/chat/completions and /v1/models with both streaming SSE and non-streaming responses. The README states it can be plugged into NextChat, OneAPI, New API, LobeChat and Codex CLI.
How do I get the Access Token that fanzha-ai-proxy needs?
The README lists three methods: pulling the app's SQLite database at /data/data/uni.app.UNIAD10B08/databases/DCStorage over ADB and querying DC_AD10B08_storage for the key 'user'; inspecting the Webview through chrome://inspect/#devices and copying the Authorization header; or capturing traffic to xzfzznt.gaj.sh.gov.cn with an intercepting proxy. All three require access to a device with the app installed and logged in.
What port does fanzha-ai-proxy listen on?
The README states the service runs on http://127.0.0.1:8088 by default, and .env.example exposes HOST and PORT as configurable values alongside DEFAULT_MODEL.
Does fanzha-ai-proxy support streaming responses?
Yes. The README says streaming SSE is fully supported, including the initial role chunk, incremental delta transmission, and a closing finish_reason: stop marker, which is what OpenAI-compatible clients expect.
Community notes