Base64 Subscription Output β
β±οΈ 7 min Β· Intermediate
Harmony's sole HTTP response is a Base64-encoded string of newline-joined VLESS links β the standard interchange format that every V2Ray/Xray/sing-box client expects when importing a subscription URL. This page dissects the complete output pipeline: how individual links are collected, how they are serialized and encoded, and what HTTP metadata accompanies the final payload.
Subscription Assembly Pipeline β
Before any encoding occurs, the worker must gather VLESS links from every configured group. The handleRequest function orchestrates this in three sequential stages: IP resolution β per-group link generation β list finalization. Each group draws from its designated IP source (static, dynamic1, or dynamic2), and for every unique IP it produces one VLESS link β capped at ipCount links per group (default: 10). With three groups by default, this yields 30 VLESS configurations in the final list.
FRESH IP EVERY REQUEST
The configsList array is initialized empty at the start of each request, meaning every subscription update fetches fresh IPs and generates new random paths and SNI casing β there is no caching between requests.
The Encoding Mechanism β
The encoding step is a single, deliberate expression:
btoa(configsList.join("\n"))This performs two operations in sequence:
configsList.join("\n")β Concatenates every VLESS link in the array with a\n(LF) newline delimiter. This is the canonical multi-configuration format specified by the V2Ray subscription convention: each link occupies exactly one line, with no trailing newline.btoa(β¦)β Applies standard Base64 encoding via the Web API built into the Cloudflare Workers runtime. Thebtoafunction takes a binary string and returns its Base64 representation. No custom alphabet, no URL-safe variant β this is the vanilla Base64 that clients decode with a simpleatob().
WHY BASE64?
The V2Ray subscription protocol mandates it. Clients like v2rayN, Nekoray, sing-box, and Clash Meta all expect the raw response body to be a Base64 string, which they decode to recover the newline-separated URI list. Harmony follows this contract exactly.
Decoded Output Structure β
After Base64 decoding, a client receives a plaintext string structured like this:
vless://uuid@ip1:port1?params#Harmonyα΅α΄ΈΛ’
vless://uuid@ip2:port2?params#Harmonyα΅α΄ΈΛ’
... (10 links per group)
vless://uuid@ip11:port11?params#Harmonyα΅αΆα΄Ύ
... (10 links per group)
vless://uuid@ip21:port21?params#Harmonyα΄±α΄ΉΛ’
... (10 links per group)Each line is a complete, self-contained VLESS URI produced by the VLESS Link Builder. The number of lines equals groups.length Γ ipCount (default: 3 Γ 10 = 30 lines).
Response Headers and Subscription Metadata β
The Base64 body is only half the contract. Harmony attaches several subscription-specific HTTP headers that clients interpret to display quota information and schedule automatic updates:
| Header | Value | Purpose |
|---|---|---|
Content-Type | text/plain; charset=utf-8 | Declares the response as Base64-encoded text (not JSON, not binary) |
Profile-Update-Interval | 6 | Tells clients to re-fetch the subscription every 6 hours |
Subscription-Userinfo | upload=β¦; download=β¦; total=β¦; expire=β¦ | Fake traffic statistics β see Fake Subscription Info Headers |
Profile-Title | Custom name or "Harmony" | Subscription display name in the client, derived from URL parameters |
Profile Title Resolution β
The Profile-Title header is set dynamically from the request URL using a priority cascade:
?name=query parameter β e.g.,https://your-worker.dev/?name=MyProxyβ title becomes"MyProxy"- URL hash fragment β e.g.,
https://your-worker.dev/#MyProxyβ title becomes"MyProxy"(fallback) - Default β If neither is provided, the title defaults to
"Harmony"
const subNameParam = url.searchParams.get("name"); // Priority 1
const subNameHash = url.hash ? decodeURIComponent(url.hash.substring(1)) : null; // Priority 2
const profileTitle = subNameParam || subNameHash || "Harmony"; // FallbackMULTI-PROFILE SUPPORT
This means a single worker deployment can serve differently-named subscriptions to different clients simply by varying the URL.
Error Handling: Graceful Degradation β
When the subscription generation fails entirely (e.g., all dynamic IP sources are unreachable and no static fallback exists), the worker does not return an HTTP error. Instead, it returns a valid Base64-encoded error message:
return new Response(btoa("# Error generating configurations"), {
status: 200,
headers: {
"Content-Type": "text/plain; charset=utf-8",
},
});β οΈ KEY DESIGN DECISIONS
- HTTP 200 is returned intentionally β many proxy clients treat non-200 responses as a subscription failure and may disable the profile entirely. Returning 200 with an error comment inside the Base64 payload prevents this.
- The error message is Base64-encoded β maintaining format consistency so clients that blindly decode the body won't crash on unexpected plaintext.
- Subscription headers are omitted β no fake userinfo or update interval is attached to error responses, avoiding misleading quota display.
- The
#prefix β mirrors the comment convention in V2Ray subscription format, where lines starting with#are treated as comments and ignored during parsing.
DEBUGGING
If you encounter # Error generating configurations after decoding your subscription, check that at least one IP source is reachable. The static IP list in staticIPs serves as the ultimate fallback β ensure it's not empty.
Complete Request-Response Flow β
The following diagram captures the full lifecycle of a subscription request, from HTTP ingress to the Base64-encoded response:
PARALLEL FETCH SAFETY
The Promise.all with 3-second timeouts ensures that slow or unresponsive IP sources don't block the entire response. If a source fails, it gracefully degrades to an empty array, and the affected group produces zero configs (unless it falls back to static).
Configuration Parameters Affecting Output β
The shape and size of the Base64 payload is controlled by two USER_SETTINGS fields:
| Parameter | Location | Default | Effect on Output |
|---|---|---|---|
ipCount | Line 35 | 10 | Number of VLESS links per group β total links = ipCount Γ groups.length |
groups[] | Lines 51β94 | 3 groups | Each group generates its own batch of links; more groups = more lines in decoded output |
TRADE-OFFS
Increasing ipCount to 20 with 3 groups would produce 60 VLESS links, making the Base64 payload roughly twice as large. The trade-off is more redundancy (more IPs to rotate through) vs. larger response size and slower client parsing.
Clients β
- **XRAY CORE CLIENTS:** - [Hiddify] - [v2rayNG] - [PattNG] β (Recommended) - [MahsaNG] - [Streisand] - [Nekoray] - [Throne] - [v2rayN] - [v2rayN-Pro] - [v2rayTun] - [Happ]
SINGBOX CORE CLIENTs:
- β (Recommended)
CLASH CORE CLIENTS:
- β (Recommended)
Next Steps β
Now that you understand how the final Base64 output is assembled and delivered, explore the adjacent pieces of the subscription pipeline:
- β How each individual
vless://URI is constructed before it entersconfigsList - β How the
Subscription-Userinfoheader fabricates realistic traffic statistics