V2Ray Subscription Formats: Base64, JSON & VLESS Links

Compare Base64 subscriptions, VLESS share links, and JSON configs. Learn what v2rayN and v2rayNG support and how to convert formats or troubleshoot import errors.

At a glance

First, distinguish the subscription URL, the content it returns, and individual node share links. Then follow a VLESS over TCP + TLS example to see how fields map between formats. This guide is for anyone whose subscription update returns no nodes, whose JSON config won't import from the clipboard, or whose imported node won't connect. The addresses, UUID, and ports shown are structural examples, not working services.

Three formats: URLs, node lists, and full configs

A “V2Ray subscription” isn't a single file format. A subscription is usually an HTTPS URL that the client accesses to retrieve a node list. The response may contain share links on separate lines, or the same list encoded as Base64. The URL retrieves and refreshes the list; the response describes the nodes. They aren't interchangeable.

FormatTypical structureImport methodWhat it contains
Base64 subscriptionDecodes to share links on separate linesURL in a subscription groupPrimarily node connection settings
VLESS share linkvless://UUID@host:port?parameters#nameImport from clipboardUsually describes one node
Native JSONIncludes keys such as inbounds and outboundsCustom config optionCan include inbounds, DNS, routing, and multiple outbounds

Base64 is encoding, not encryption. Anyone who can decode it can usually see server addresses and credentials. Never post a subscription URL, decoded node list, or full config in a public forum. A token in a subscription URL may also let others keep fetching updates, so don't share it just because it doesn't look like a password.

How to tell: inspect the decoded content

If you see multiple protocol links on separate lines, it's a node list. If you see an object with inbounds and outbounds, it's a full config. Don't identify the format by its file extension or text length.

v2rayN and v2rayNG: choose the right import method

v2rayN is a desktop client; v2rayNG is an Android client that uses the Xray core. Both commonly use subscription workflows for node lists, but supported protocols and parameters also depend on the client and core versions. “Supports JSON” doesn't mean the subscription update feature accepts any JSON file.

Subscription URL

Recommended

Add the provider's subscription URL to a subscription group. Future updates fetch the list from that URL, making this the right option for services whose nodes change.

Best for: node lists that need regular updates

Individual share link

Copy the complete vless:// or vmess:// link, then import it from the clipboard. Importing a link once doesn't create an updatable subscription.

Best for: testing a single node and checking its settings

Custom JSON

Use the client's custom config feature and make sure the config matches the selected core. A full config may control DNS and routing, so checking only the server address isn't enough.

Best for: configs that need to preserve routing or special outbounds

  1. Create a subscription group

    In v2rayN, open “Subscription Group” → “Subscription Group Settings” from the main window. Add a group and enter the subscription URL. Enter the URL here; don't paste the full Base64 text.

  2. Update nodes

    Open the “Subscription Group” menu and select “Update all subscriptions (without proxy).” If the URL requires an existing proxy, try the corresponding “Update via proxy” option. Menu wording and punctuation may vary slightly between versions.

  3. Test a single link

    In v2rayN, choose “Servers” → “Import batch URLs from clipboard.” In v2rayNG, tap “+” on the main screen → “Import from clipboard.” Copy only the protocol link itself, without quotes or explanatory text.

  4. Android subscriptions

    In v2rayNG, open “Subscription group settings” from the menu in the top-right corner of the main screen. Tap “+” to add and save a URL, then return to the main screen and select “Update subscription” from the menu. If the menu labels differ in your version, look for the subscription group and update options.

v2flyNG uses the v2fly core, so don't assume every extension parameter intended for Xray works unchanged. In particular, confirm core support before using REALITY or specific flow-control settings. The field-mapping example in this guide is for Xray and doesn't guarantee compatibility across cores.

Decode and re-encode Base64: only change the outer wrapper

A typical Base64 subscription is made by putting each node link on its own line, then encoding the entire UTF-8 text. So decoding it should usually produce links, not JSON. Some providers return a plain-text list of links, which doesn't need decoding.

On a Mac, copy the Base64 subscription content, then run the command below in Terminal. It reads the clipboard and prints the result in the current terminal; it doesn't access the subscription URL. The output contains credentials, so avoid sharing your terminal screen while running it.

pbpaste | base64 -D

To reverse the process, save the share links one per line in a local plain-text file, then encode the file. The command below assumes nodes.txt already exists in the current directory. It creates a static text file, not a subscription URL that a client can update automatically.

base64 -i nodes.txt -o subscription.txt

Convert vless:// to JSON: map fields one by one

This TCP + TLS example shows the minimum field mapping. The server domain is reserved for documentation examples, and the UUID is illustrative; neither can be used to connect. For a working config, get the matching address, port, UUID, and TLS settings from your provider. Replacing only the domain won't make it work.

vless://[email protected]:443?encryption=none&security=tls&type=tcp&sni=node.example.com#Example-TLS
443
Example remote TLS port
10808
Example local SOCKS port
36
Number of characters in the hyphenated example UUID

These numbers illustrate the config; they aren't speed-test results or defaults for every client. The remote port and local listening port are at opposite ends of the connection and don't need to match. The Xray config below illustrates the field mapping and listens only on the local loopback address.

{
  "log": {
    "loglevel": "warning"
  },
  "inbounds": [
    {
      "tag": "local-socks",
      "listen": "127.0.0.1",
      "port": 10808,
      "protocol": "socks",
      "settings": {
        "auth": "noauth",
        "udp": true
      }
    }
  ],
  "outbounds": [
    {
      "tag": "proxy",
      "protocol": "vless",
      "settings": {
        "vnext": [
          {
            "address": "node.example.com",
            "port": 443,
            "users": [
              {
                "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
                "encryption": "none"
              }
            ]
          }
        ]
      },
      "streamSettings": {
        "network": "tcp",
        "security": "tls",
        "tlsSettings": {
          "serverName": "node.example.com"
        }
      }
    }
  ]
}
Link fieldJSON locationNotes
UUIDsettings.vnext[0].users[0].idAuthentication credential; don't change it arbitrarily
Host and portsettings.vnext[0].address and portJSON port must be a number
encryption=noneusers[0].encryptionVLESS field; it doesn't mean TLS is disabled
type=tcpstreamSettings.networkTransport type; must match the server
security=tlsstreamSettings.securityTLS is selected here as the security layer
snitlsSettings.serverNameMay differ from the connection address
#Example-TLSClient-side node labelNot part of the protocol handshake

For WebSocket, gRPC, REALITY, or Vision, you'll also need to map fields such as the path, service name, public key, short ID, fingerprint, or flow. Don't add flow=xtls-rprx-vision to a TCP example and assume the conversion is complete. Check the transport, server config, and core support together.

Convert JSON to a share link: what gets left out

To convert in the other direction, find the target outbound and read its protocol, server, user, and transport settings. The JSON above has a single VLESS outbound, so it can be represented by one link. If the config contains multiple servers or users, generate a separate link for each; one URI can't represent them all.

  1. Confirm protocol: "vless", then read the address, port, and user UUID from vnext.
  2. Set the transport network and security type in type and security, then add the required protocol query parameters.
  3. Percent-encode query parameter values and the label. For example, encode the path /edge?x=1 as %2Fedge%3Fx%3D1 so the question mark isn't misread.
  4. For an IPv6 server address, put the address in square brackets in the URI. Don't split the entire address at each colon.
  5. Import the link into the target client again, check each field in the node editor, then test the connection.

Bottom line: converting a node isn't migrating a full config

Keep the original JSON if you need to preserve DNS, routing rules, selection between multiple outbounds, or local inbounds. Share links are only suitable for node settings they can represent.

Even after a link imports successfully, the client still uses its own system proxy, TUN, DNS, and routing settings. The original JSON's “direct for mainland China, proxy for everything else” rule won't carry over with a VLESS node. The system proxy determines which apps send requests to the client; routing rules determine which outbound handles those requests. These are separate layers.

Import errors and connection failures: troubleshoot by stage

First identify where the failure happens: the subscription request fails, the response can't be parsed, or the node appears in the list but won't connect. If the node appears, at least some of the format was parsed; that doesn't confirm the UUID, TLS settings, or remote service are correct.

Why are there no nodes after a successful subscription update?

Check the selected subscription group and list filters, then look at the update log for a message that zero valid nodes were found. If the response is actually a login page, expiration notice, or full JSON config, ask the provider which subscription format works with your client. Re-encoding the same content repeatedly won't help.

Why does pasting JSON show “no valid config”?

The regular clipboard import for nodes usually expects share links. Import full JSON through the custom config feature, and check commas, double quotes, and the top-level structure. JSON doesn't allow comments or trailing commas. Even if the syntax is valid, make sure the config matches the selected core.

Why does the link import, but the TLS handshake fails?

Check the remote port, security, SNI, and system time first, then confirm the transport type matches the server's requirements. Disabling certificate verification isn't a routine fix. Resolving the address and matching the certificate name are two separate checks.

Does a subscription URL timeout mean I need to enable TUN?

Not necessarily. If you have a working node, try the client's option to update through a proxy. If you don't, first check whether your current network can reach the subscription URL. If the log reports that a local port is already in use, stop duplicate client processes or change the listening port.

Why can the converted node connect, but my app still can't?

Check whether the app uses the system proxy and whether its proxy port matches the client's. Command-line tools may not use the system proxy, so a browser test alone can't tell you whether every app will work. Before enabling TUN, check permissions, routing, and DNS. Avoid changing several settings at once so you can trace the problem.

Download v2rayNChoose a client for your platform