APIs
The subsection converter is actually an API. And to support proxy-provider, I implemented another API.
Here I'm gonna introduce the APIs.
Telegram SOCKS links (tg://socks?... and https://t.me/socks?...) produce mihomo socks5 nodes. MTProto links (tg://proxy?... and https://t.me/proxy?...) are unsupported and fail the whole conversion with 400 for direct input or 502 for upstream subscriptions. Oversized integer fields that cannot be serialized also fail the upstream subscription with 502.
GET /sub
This is the API for subsection converter. It's contained in the link generated by the web ui.
It accepts GET requests. Here're the parameters:
| Parameter | Description | Optional | Default | Remarks |
|---|---|---|---|---|
| url | The URL of the original subscription or node sharing link. It needs to be URIComponent encoded. | No | - | Multiple subscription links are supported. You can use line breaks or "|" to separate them. https://t.me/... links are treated as standalone share links (parsed as V2Ray nodes), not as remote subscription URLs. |
| template | Template ID used to render the final config. | Yes | zju | Built-in values are zju and general. When omitted, zju is used. |
| interval | The interval of proxy update. | Yes | 1800 | Unit: seconds; integer from 1 to 2147483647. |
| urlstandby | The URL of the standby subscription or node sharing link. The proxies in it will only be added to the manual switch group (the group whose "manual" is True in the configuration file), and will not be classified into region groups. It's recommended to be URIComponent encoded. | Yes | - | Multiple subscription links are supported. You can use line breaks or " |
| short | If this parameter is set (regardless of its value), the header section and dns section containing allow-lan will not be generated. | Yes | - | - |
| npr | If this parameter is set (regardless of its value), the URL of the ruleset will not be proxied. | Yes | - | By default, this service is used to proxy the URL of the ruleset to ensure that the ruleset can be obtained normally. If this parameter is set, the URL of the ruleset will not be proxied. |
GET /provider
This API converts the subscription to the configuration required by proxy-provider. This API will be called whenever the proxy is updated via proxy-provider.
It accepts GET requests. Here're the parameters:
| Parameter | Description | Optional | Default | Remarks |
|---|---|---|---|---|
| url | The URL of the original subscription. It needs to be URIComponent encoded. | No | - | Should be a single subscription link. |
GET /config
This API returns the runtime configuration used by the Web UI. It accepts GET requests and takes no parameters.
Response JSON fields:
| Field | Description |
|---|---|
| defaultTemplate | The template name used when /sub or /proxy omits the template query parameter (from DEFAULT_TEMPLATE in config.yaml). |
| availableTemplates | A list of all template names found in the template/ directory. |
GET /robots.txt
Returns a robots.txt response based on the DISALLOW_ROBOTS setting in config.yaml. When DISALLOW_ROBOTS=true, it returns User-agent: * / Disallow: /; otherwise it returns 404.
GET /proxy
This API is used to access the specified URL through this service. It accepts GET requests. Here're the parameters:
| Parameter | Description | Optional | Default | Remarks |
|---|---|---|---|---|
| url | The URL to be proxied. It needs to be URIComponent encoded. | No | - | Use this service to access this URL and return the result. |
| template | Template ID used for rule whitelist validation. | Yes | zju | This should match the template used in /sub; the generated config already includes it when needed. |
Errors and limits
Invalid standalone share links return HTTP 400. Invalid subscriptions fetched from an upstream return HTTP 502, including the source index and share-link line number when available; conversion fails as a whole instead of dropping failed nodes. Unexpected server defects still return HTTP 500. Invalid interval values return HTTP 400 before any upstream request.
/sub requires at least one non-empty primary source; standby sources alone return HTTP 400.
Blank lines and # metadata comments (including URLs) are ignored in share-link subscriptions, in both plain text and Base64 form. A recognizable malformed link such as trojan:/... still fails the whole conversion.
Upstream HTTP errors return HTTP 502 without exposing the upstream body. Private-network targets return HTTP 403 unless ALLOW_PRIVATE_NETWORKS is enabled. This also applies to /proxy, which additionally requires the URL to appear in the selected template's RULESET.
Base64 envelopes use standard padded or unpadded Base64, allowing CR/LF line breaks as mihomo does. Invalid characters and data after padding are never silently discarded.
Within one upstream redirect chain, cookies follow their domain, path and HTTPS restrictions; separate subscription fetches do not share cookies. Invalid initial HTTP URLs return 400, while invalid redirect targets supplied by an upstream return 502.
Subscriptions support YAML anchors, aliases and merge keys; output may contain aliases supported by mihomo and Stash. Inputs, upstream responses and expanded YAML scalar data are limited to 10 MiB, YAML nesting to 32 levels, and the expanded YAML graph to 100,000 nodes. Recursive aliases are rejected. Response bodies have a 30-second read timeout. If a streamed /proxy response fails after headers have been sent, the stream is aborted and resources are closed.
Unquoted YAML on, off, yes and no remain strings, matching mihomo subscription mappings; true and false remain booleans.
Upstream response bodies support identity, gzip and deflate, with up to four compression layers. Both wire data and each decompression layer are limited to 10 MiB; allocation is bounded during decoding, before accepting expanded data. Unsupported encodings and malformed compressed streams fail conversion.
Each parsed subscription supports at most 10,000 proxies and 10 MiB of expanded scalar fields, including repeated credentials, nested options and node names. This budget covers every protocol and Clash YAML. Mieru multi-port expansion is also checked before allocating per-port models. Exceeding a budget fails the whole conversion. YAML responses are serialized in a worker thread.
TCP connections race validated addresses at 250 ms intervals under one connection deadline. Only the winning connection sends the HTTP request; Host, TLS SNI and DNS pinning are preserved.