SEO blog post
This commit is contained in:
261
articles/devto-hashnode/devto-wifi-qr-code-protocol-spec.md
Normal file
261
articles/devto-hashnode/devto-wifi-qr-code-protocol-spec.md
Normal file
@@ -0,0 +1,261 @@
|
||||
---
|
||||
title: "Wi-Fi QR Code Protocol: WIFI: String Syntax Specification & Mobile OS Parsing"
|
||||
description: "A comprehensive developer guide to the unofficial WIFI: URI protocol specification, character escaping rules, WPA2/WPA3 network formats, and creating a print qr code for Wi-Fi access."
|
||||
tags: networking, mobile, webdev, security
|
||||
keywords: qr wifi, wifi qr code generator, print qr code, print a qr code, free static qr code generator, static qr code generator
|
||||
canonical_url: https://www.qrmaster.net/blog/wifi-qr-code-generator
|
||||
---
|
||||
|
||||
# Wi-Fi QR Code Protocol: WIFI: String Syntax Specification & Mobile OS Parsing
|
||||
|
||||
Scanning a **qr wifi** code to automatically connect a smartphone to a Wi-Fi network without manually typing complex WPA3 passwords is one of the most common physical tech interactions.
|
||||
|
||||
Unlike vCards or geo-locations which have formal IETF RFC standards, a **wifi qr code generator** uses an de facto industry standard string syntax originally popularized by ZXing ("Zebra Crossing").
|
||||
|
||||
In this technical guide, we will inspect the exact `WIFI:` connection string syntax, character escaping rules, WPA2/WPA3 security flags, hidden network parameters, and build a TypeScript utility to generate a **print qr code** for physical tabletop stands using a **free static qr code generator**.
|
||||
|
||||
---
|
||||
|
||||
## 1. The `WIFI:` String Protocol Syntax
|
||||
|
||||
The payload generated by a **wifi qr code generator** is a formatted key-value string prefixed with `WIFI:`.
|
||||
|
||||
### Protocol Format:
|
||||
```text
|
||||
WIFI:S:<SSID>;T:<SECURITY_TYPE>;P:<PASSWORD>;H:<HIDDEN_FLAG>;;
|
||||
```
|
||||
|
||||
### Parameter Specification:
|
||||
|
||||
| Parameter Key | Description | Allowed Values | Required? |
|
||||
|---|---|---|---|
|
||||
| **S** | Network SSID (Name) | Any string (UTF-8) | ✅ Mandatory |
|
||||
| **T** | Security Encryption Type | `WPA`, `WEP`, `nopass` | ✅ Mandatory |
|
||||
| **P** | Pre-shared Key (Password) | Network password string | Conditional (Skip if `nopass`) |
|
||||
| **H** | Hidden SSID Flag | `true` or `false` | Optional (Default: `false`) |
|
||||
|
||||
---
|
||||
|
||||
## 2. Character Escaping Rules: Avoiding Connection Failures
|
||||
|
||||
The most frequent bug when building a **wifi qr code generator** is failing to escape special delimiter characters in the SSID or Password.
|
||||
|
||||
### Characters Requiring Backslash Escaping (`\`):
|
||||
If an SSID or Wi-Fi password contains any of the following four characters:
|
||||
- Colon `:`
|
||||
- Semicolon `;`
|
||||
- Backslash `\`
|
||||
- Comma `,`
|
||||
|
||||
They **must be escaped with a preceding backslash (`\`)**.
|
||||
|
||||
### Escaping Examples:
|
||||
|
||||
```text
|
||||
# Example 1: SSID containing a semicolon ("Coffee;Bar") and password "secret:123"
|
||||
WIFI:S:Coffee\;Bar;T:WPA;P:secret\:123;;
|
||||
|
||||
# Example 2: Unencrypted Open Network ("Guest_WiFi")
|
||||
WIFI:S:Guest_WiFi;T:nopass;;
|
||||
|
||||
# Example 3: Hidden WPA2/WPA3 Network ("Vault") with password "P@$$w0rd"
|
||||
WIFI:S:Vault;T:WPA;P:P@$$w0rd;H:true;;
|
||||
```
|
||||
|
||||
> **Important**: Notice the double semicolon (`;;`) at the very end of the string. Mobile camera scanners use the trailing double semicolon as the string termination marker when parsing **qr wifi** codes!
|
||||
|
||||
---
|
||||
|
||||
## 3. iOS vs. Android OS Parser Behavior
|
||||
|
||||
Understanding how mobile operating systems parse `WIFI:` barcodes prevents support headaches when users **print a qr code**.
|
||||
|
||||
```
|
||||
┌───────────────────────────┬───────────────────────────────────────────┬───────────────────────────────────────────┐
|
||||
│ Feature │ Apple iOS (Camera App) │ Android (Google Lens / Native Scanner) │
|
||||
├───────────────────────────┼───────────────────────────────────────────┼───────────────────────────────────────────┤
|
||||
│ User Interaction Prompt │ Displays banner: "Join 'SSID' Network?" │ Displays modal with "Connect to Network" │
|
||||
│ One-Tap Auto Connect │ ✅ Yes (Connects without typing password) │ ✅ Yes (Saves & connects automatically) │
|
||||
│ WPA3 Compatibility │ Map `T:WPA` for both WPA2 & WPA3 │ Map `T:WPA` for both WPA2 & WPA3 │
|
||||
│ Enterprise (802.1X / EAP)│ ❌ Unsupported via standard `WIFI:` string│ ❌ Requires mobile profile (.mobileconfig)│
|
||||
└───────────────────────────┴───────────────────────────────────────────┴───────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
*Note on WPA3:* Neither iOS nor Android requires a separate `T:WPA3` tag. Specifying `T:WPA` in your **static qr code generator** covers WPA, WPA2, and WPA3 Personal networks seamlessly.
|
||||
|
||||
---
|
||||
|
||||
## 4. TypeScript Implementation: Wi-Fi Payload Generator
|
||||
|
||||
Below is a complete, production-ready TypeScript utility class that formats, escapes, and validates payloads for a **free static qr code generator**.
|
||||
|
||||
### `src/services/wifiPayloadBuilder.ts`
|
||||
|
||||
```typescript
|
||||
export type WifiSecurityType = 'WPA' | 'WEP' | 'nopass';
|
||||
|
||||
export interface WifiConfig {
|
||||
ssid: string;
|
||||
password?: string;
|
||||
securityType: WifiSecurityType;
|
||||
isHidden?: boolean;
|
||||
}
|
||||
|
||||
export class WifiPayloadBuilder {
|
||||
/**
|
||||
* Generates a fully escaped, validated WIFI: connection string.
|
||||
*/
|
||||
public static buildPayload(config: WifiConfig): string {
|
||||
const { ssid, password = '', securityType, isHidden = false } = config;
|
||||
|
||||
if (!ssid || ssid.trim().length === 0) {
|
||||
throw new Error('Wi-Fi SSID is mandatory.');
|
||||
}
|
||||
|
||||
if (securityType !== 'nopass' && (!password || password.length === 0)) {
|
||||
throw new Error(`Password is required for security type "${securityType}".`);
|
||||
}
|
||||
|
||||
// Escape special delimiter characters
|
||||
const escapedSSID = this.escapeString(ssid);
|
||||
const escapedPassword = securityType !== 'nopass' ? this.escapeString(password) : '';
|
||||
|
||||
let payload = `WIFI:S:${escapedSSID};T:${securityType};`;
|
||||
|
||||
if (securityType !== 'nopass') {
|
||||
payload += `P:${escapedPassword};`;
|
||||
}
|
||||
|
||||
if (isHidden) {
|
||||
payload += `H:true;`;
|
||||
}
|
||||
|
||||
// Append compulsory double-semicolon termination marker
|
||||
payload += ';';
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
private static escapeString(str: string): string {
|
||||
return str.replace(/([\\;:,])/g, '\\$1');
|
||||
}
|
||||
|
||||
public static isValidWifiPayload(payload: string): boolean {
|
||||
return payload.startsWith('WIFI:') && payload.endsWith(';;');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. How to Print a QR Code: Printable Wi-Fi Tabletop Sign Template
|
||||
|
||||
When you **print a qr code** for physical venues (hotels, cafes, coworking spaces), pairing the vector barcode with clean printable HTML typography ensures guests know how to scan **qr wifi**.
|
||||
|
||||
### Example Printable HTML Template (`public/wifi-stand-card.html`):
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Wi-Fi Access Sign - Print QR Code</title>
|
||||
<style>
|
||||
@media print { body { -webkit-print-color-adjust: exact; } }
|
||||
body { font-family: 'Inter', system-ui, sans-serif; display: flex; justify-content: center; align-items: center; min-height: 100vh; background: #F8FAFC; margin: 0; }
|
||||
.card { background: white; width: 320px; padding: 36px 28px; border-radius: 20px; box-shadow: 0 10px 25px rgba(0,0,0,0.08); text-align: center; border: 1px solid #E2E8F0; }
|
||||
h1 { font-size: 22px; color: #0F172A; margin: 0 0 6px; }
|
||||
p.subtitle { color: #64748B; font-size: 14px; margin: 0 0 24px; }
|
||||
.qr-container { background: #F1F5F9; padding: 16px; border-radius: 16px; display: inline-block; margin-bottom: 24px; }
|
||||
.qr-container svg { display: block; }
|
||||
.info-box { background: #F8FAFC; padding: 12px 16px; border-radius: 12px; border: 1px solid #E2E8F0; text-align: left; font-size: 13px; }
|
||||
.info-row { display: flex; justify-content: space-between; margin-bottom: 6px; }
|
||||
.info-row:last-child { margin-bottom: 0; }
|
||||
.label { color: #64748B; font-weight: 500; }
|
||||
.val { color: #0F172A; font-weight: 600; font-family: monospace; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="card">
|
||||
<h1>Connect to Wi-Fi</h1>
|
||||
<p class="subtitle">Scan with your phone camera to join</p>
|
||||
|
||||
<div class="qr-container">
|
||||
<!-- Insert Vector SVG QR Code Here -->
|
||||
<svg width="180" height="180" viewBox="0 0 180 180">
|
||||
<!-- SVG Paths -->
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div class="info-box">
|
||||
<div class="info-row">
|
||||
<span class="label">Network:</span>
|
||||
<span class="val">Guest_Lounge_5G</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="label">Password:</span>
|
||||
<span class="val">Welcome2026!</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. End-to-End Test Suite with Jest
|
||||
|
||||
Let's write a unit test suite to verify string escaping and boundary conditions.
|
||||
|
||||
### `tests/wifiPayload.test.ts`
|
||||
|
||||
```typescript
|
||||
import { WifiPayloadBuilder } from '../src/services/wifiPayloadBuilder';
|
||||
|
||||
describe('WifiPayloadBuilder', () => {
|
||||
test('should generate standard WPA2 payload', () => {
|
||||
const payload = WifiPayloadBuilder.buildPayload({
|
||||
ssid: 'MyHomeWiFi',
|
||||
password: 'SuperSecretPassword123',
|
||||
securityType: 'WPA',
|
||||
});
|
||||
expect(payload).toBe('WIFI:S:MyHomeWiFi;T:WPA;P:SuperSecretPassword123;;');
|
||||
});
|
||||
|
||||
test('should escape colons and semicolons in SSID and Password', () => {
|
||||
const payload = WifiPayloadBuilder.buildPayload({
|
||||
ssid: 'Cafe;WiFi:5G',
|
||||
password: 'pass;word:123,key\\',
|
||||
securityType: 'WPA',
|
||||
});
|
||||
expect(payload).toBe('WIFI:S:Cafe\\;WiFi\\:5G;T:WPA;P:pass\\;word\\:123\\,key\\\\;;');
|
||||
});
|
||||
|
||||
test('should handle open unencrypted networks', () => {
|
||||
const payload = WifiPayloadBuilder.buildPayload({
|
||||
ssid: 'FreePublicWiFi',
|
||||
securityType: 'nopass',
|
||||
});
|
||||
expect(payload).toBe('WIFI:S:FreePublicWiFi;T:nopass;;');
|
||||
});
|
||||
|
||||
test('should include hidden flag when network is hidden', () => {
|
||||
const payload = WifiPayloadBuilder.buildPayload({
|
||||
ssid: 'HiddenNetwork',
|
||||
password: 'secretpassword',
|
||||
securityType: 'WPA',
|
||||
isHidden: true,
|
||||
});
|
||||
expect(payload).toBe('WIFI:S:HiddenNetwork;T:WPA;P:secretpassword;H:true;;');
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Conclusion
|
||||
|
||||
Understanding the `WIFI:` payload specification and implementing strict character escaping in a **wifi qr code generator** ensures seamless, friction-free auto-connections when you **print a qr code** for hotel guests, restaurant customers, and office visitors.
|
||||
|
||||
To generate customizable vector Wi-Fi QR codes with custom brand colors, logo embedding, and printable tabletop stand templates, check out [QR Master Free Wi-Fi QR Generator](https://www.qrmaster.net/blog/wifi-qr-code-generator).
|
||||
Reference in New Issue
Block a user