A WiFi QR code holds a network name, a security type and a password in one scannable string. Point a phone camera at it and the phone offers to join the network, so nobody has to read the password off a whiteboard. Image-Charts renders one from a single URL that carries cht=qr and the credentials in chl.
Put the network details in a WIFI: payload, URL-encode it, and pass it as the chl parameter of a cht=qr chart. The response is a PNG you can use anywhere an image goes.
The payload you encode
WIFI:T:WPA;S:Demo;P:hunter2;;
The URL you request
https://image-charts.com/chart?cht=qr&chs=300x300&chl=WIFI%3AT%3AWPA%3BS%3ADemo%3BP%3Ahunter2%3B%3B
The payload format comes from ZXing, the barcode library the first Android scanners shipped with, and it is what the iOS Camera app and the Android scanner read when they offer to join a network. Fields are separated by semicolons, and the payload closes with two of them.
| Field | Meaning | Notes |
|---|---|---|
| T: | Security type | WPA covers WPA, WPA2 and WPA3. WEP for an old network, nopass for an open one. |
| S: | Network name (SSID) | Exactly as it is broadcast. Case sensitive. |
| P: | Password | Leave it out when the type is nopass. |
| H: | Hidden network | H:true when the SSID is not broadcast. Omit it otherwise. |
| ;; | End of the payload | Two semicolons close the string. |
Two passes, in this order. Inside S: and P:, a backslash escapes the five characters that would otherwise end a field (backslash, semicolon, comma, colon, double quote), so a password of p;ss is written p\;ss. Then URL-encode the whole payload once, because those same semicolons and colons carry meaning in a query string. WIFI:T:WPA;S:Demo;P:hunter2;; becomes WIFI%3AT%3AWPA%3BS%3ADemo%3BP%3Ahunter2%3B%3B.
An open guest network needs no password field. Its payload is WIFI:T:nopass;S:Guest;; and it renders the same way.
cht, chs and chl are required. The rest decide how the code is drawn.
| Parameter | What It Controls | Values |
|---|---|---|
| cht=qr | Chart type | Required. |
| chs | Size in pixels, width x height | Required. A QR code is square, so the width decides. Below 29 pixels wide the API returns a blank square instead of an unreadable code. |
| chl | The data to encode | Required, UTF-8 URL-encoded. A URL tops out near 2K, so a longer payload goes through a POST request. |
| chld | Error correction level and margin | L is the default, then M, Q and H, recovering 7%, 15%, 25% and 30% of a damaged code. The margin is a border width counted in rows, 4 by default, and unsigned charts widen it so the watermark stays legible. |
| icqrf | Foreground color, RRGGBB or RRGGBBAA | Default 000000. |
| icqrb | Background color | Default FFFFFF. An alpha channel of 00 makes it transparent. |
| chof | Output format | .png by default, .svg for vector output. |
| choe | Data encoding | UTF-8, the only supported value. |
A higher error correction level survives a scuffed sticker or a code someone dropped a logo onto, at the cost of holding less data in the same square. A WiFi payload is short, so H costs you nothing here.
The password sits in the URL, so it travels wherever that URL travels, into browser history, server logs, a CDN cache and the analytics of the page that embeds it. Our privacy policy covers what happens on our side. For a café guest network this is the whole point. For a network you care about, render the code once, keep the image and drop the URL, or run the API inside your own network with Image-Charts On-Premise.
If the codes come out of a scheduled job or a no-code tool rather than your own code, the integrations and the agent tooling reach the same API without a rewrite.