# WeChat Mini Program HTTPS: server domains, SSL chain, TLS 1.2

> Make a WeChat Mini Program reach your API: ICP-filed domain, trusted certificate with full chain, TLS 1.2+, server domains, handshake fixes.

Source: https://ssl.sh/guides/wechat-mini-program-https/
Last updated: 2026-11-10

A WeChat Mini Program can call your API only if its domain, such as `api.example.com`, has an ICP filing, a trusted certificate with a complete chain and TLS 1.2 or later, and is registered as a server domain in the Mini Program console.

The rules come from the WeChat Mini Program documentation as of November 2026. The English pages are translations; where they read ambiguously, the steps follow the stricter interpretation.

## Prerequisites

WeChat is stricter about server domains than a browser.

- A domain with an ICP filing, for example `api.example.com`, with an `A` record pointing at your server, for example `203.0.113.10`. ICP filing is a registration with China's Ministry of Industry and Information Technology, normally submitted through a hosting or cloud provider that operates in the Chinese mainland, and it takes time, so start early.
- An API already reachable over HTTPS, with a certificate from a publicly trusted CA (Let's Encrypt and the free Alibaba Cloud or Tencent Cloud certificates all qualify). Self-signed certificates do not work.
- Administrator or developer access to the Mini Program in the WeChat Official Accounts Platform (the Mini Program console).

## Step 1: Check the chain and TLS 1.2

A missing intermediate certificate is the most common reason a Mini Program fails on phones while the same URL opens fine in a desktop browser, because desktop browsers often fill gaps in the chain themselves.

```bash
openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts </dev/null 2>/dev/null | grep -E '^ *[0-9] s:'
openssl s_client -connect api.example.com:443 -servername api.example.com -tls1_2 </dev/null 2>/dev/null | grep -E 'Protocol|Cipher'
```

The first command should list at least two certificates (depth 0 and 1); the second should negotiate TLSv1.2. If the chain is short, fix it with [install an intermediate certificate](https://ssl.sh/guides/install-intermediate-certificate/) or build the file with the [chain builder](https://ssl.sh/tools/chain-builder/).

## Step 2: Use a sound TLS configuration on the server

With Nginx, point `ssl_certificate` at the full chain and enable TLS 1.2 and 1.3:

```nginx
server {
    listen 443 ssl;
    http2 on;    # nginx 1.25.1+; older versions use "listen 443 ssl http2;"
    server_name api.example.com;

    ssl_certificate     /etc/letsencrypt/live/api.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
    ssl_protocols       TLSv1.2 TLSv1.3;

    location / {
        proxy_pass http://127.0.0.1:3000;
    }
}
```

No certificate yet? Follow [Nginx with Let's Encrypt](https://ssl.sh/guides/nginx-lets-encrypt-certbot/) or [Tencent Cloud SSL certificate](https://ssl.sh/guides/tencent-cloud-ssl-certificate/).

## Step 3: Register the server domains

In the Mini Program console go to **Development → Development Settings → Server Domains** and edit the lists:

- **request** domains: `https://api.example.com`
- **socket** domains: `wss://api.example.com`, if you use WebSocket
- **uploadFile** and **downloadFile** domains: as needed

The rules that catch people out:

- Only `https://` and `wss://` entries are accepted, and IP addresses (other than the Mini Program's LAN IP, allowed from base library 2.4.0) and `localhost` are rejected.
- If you configure a port, such as `https://api.example.com:8443`, only that exact origin works. If you configure none, the request URL must not include a port at all, not even `:443`. WSS entries need no port and allow any.
- `api.weixin.qq.com` cannot be configured; call it from your server, not from the Mini Program.
- Each change counts against a limited number of edits, shown in the console.

## Step 4: Test on real phones

Test on real phones with domain and certificate validation turned on. The WeChat developer tools have a local setting that skips validation of legal domains, web-view (business) domains, TLS versions and HTTPS certificates; it exists for local debugging only. Clear it, then test with real-device debugging or a preview QR code on both an iPhone and an Android phone. iOS additionally applies Apple's App Transport Security rules and rejects self-signed certificates.

## Verify

The API domain should show a complete chain, TLS 1.2 or 1.3 support and a future expiry date. Check it with the [SSL checker](https://ssl.sh/tools/ssl-checker/), or from any terminal:

```bash
curl ssl.sh/api.example.com
```

## Automatic renewal

Renewing the certificate changes nothing in the Mini Program console, because the domain stays the same. The real risk is expiry: once the certificate expires, every request from every user fails, and users get no warning they could click through. Three measures prevent that:

- Renew automatically with Certbot, acme.sh or similar, and reload Nginx after each renewal; see [renew certificates automatically](https://ssl.sh/guides/renew-certificates-automatically/).
- Free cloud certificates are short-lived as well (Tencent Cloud's free certificate lasts 3 months) and all public certificates are capped at 200 days since March 15, 2026 and 47 days from March 15, 2029, so manual replacement will eventually slip.
- Add the API domain to [ssl.sh monitoring](https://ssl.sh/monitor/) (in development) to get a warning before expiry.

## Troubleshooting

- **request:fail url not in domain list**: the domain is not registered, or the scheme or port differs; see the FAQ.
- **request:fail ssl hand shake error**: incomplete chain, no TLS 1.2, an expired certificate or a name mismatch; see [missing intermediate certificate](https://ssl.sh/errors/missing-intermediate-certificate/) and [ERR_SSL_VERSION_OR_CIPHER_MISMATCH](https://ssl.sh/errors/err-ssl-version-or-cipher-mismatch/).
- **Works on Android, fails on iOS (or the reverse)**: almost always the chain; the platforms differ in how they complete missing intermediates.
- **Self-signed certificate**: Mini Programs do not trust it; use a publicly trusted CA, see [self-signed certificate in certificate chain](https://ssl.sh/errors/self-signed-certificate-in-certificate-chain/).
- **Every request suddenly fails**: the certificate expired; see [NET::ERR_CERT_DATE_INVALID](https://ssl.sh/errors/net-err-cert-date-invalid/), then add automatic renewal and monitoring.
