← Back to Guides
βš™οΈ Technical 10 min read

WiFi QR Code Format Explained (Technical)

Deep dive into the technical specification of WiFi QR codes. Perfect for developers and IT professionals.

WiFi QR codes use a standardized format that allows mobile devices to automatically connect to wireless networks by scanning a two-dimensional barcode. This guide explains the technical specification, encoding rules, and implementation details for developers and IT professionals.

Whether you're building a QR code generator, implementing network provisioning features, or just curious about how the technology works, this guide covers everything you need to know.

πŸ“‹ Quick Reference

Format: WIFI:T:[type];S:[ssid];P:[password];H:[hidden];;​

Example:

WIFI:T:WPA;S:MyNetwork;P:MyPassword123;;

πŸ“ WiFi QR Code Format Specification

Standard Format

WiFi QR codes follow a specific format based on the MECARD-like syntax:

WIFI:T:<encryption_type>;S:<ssid>;P:<password>;H:<hidden>;;

Field Breakdown:

  • WIFI: Protocol identifier (required, case-sensitive)
  • T: Authentication type (required)
    Values: WPA, WPA2, WPA3, WEP, nopass (for open networks)
  • S: SSID (network name, required)
    UTF-8 string, special characters must be escaped
  • P: Password (optional, omit for open networks)
    UTF-8 string, special characters must be escaped
  • H: Hidden network flag (optional, default: false)
    Values: true (hidden), false or omitted (visible)
  • ;; Double semicolon terminator (required at end)

πŸ”€ Character Encoding & Escaping Rules

Special Characters That Must Be Escaped

Certain characters have special meaning in the WiFi QR format and must be escaped with a backslash:

CharacterEscape SequenceReason
;\;Field separator
:\:Key-value separator
,\,Value separator (legacy)
"\"Quote character
\\\Escape character itself

Examples: Before and After Escaping

SSID with semicolon:

Original: Coffee;Shop

Escaped: Coffee\;Shop

Password with special characters:

Original: Pass:word;123"test"

Escaped: Pass\:word\;123\"test\"

Complete example:

Original values:

SSID: My;Network

Password: Pass\word:123

Result:

WIFI:T:WPA;S:My\;Network;P:Pass\\word\:123;;

πŸ” Authentication Types (T Parameter)

WPA / WPA2Recommended

Format: T:WPA (covers both WPA and WPA2)

Most common for modern home and business networks. Provides strong encryption.

WIFI:T:WPA;S:MyNetwork;P:SecurePassword123;;

WPA3Latest Standard

Format: T:WPA (WPA3 uses same format)

Latest WiFi security standard (2018+). Stronger encryption than WPA2. Devices negotiate WPA3/WPA2 automatically.

WIFI:T:WPA;S:MyWPA3Network;P:VerySecurePass!;;

WEPDeprecated

Format: T:WEP

Legacy encryption (1990s). Easily cracked. Only use for very old devices that don't support WPA.

WIFI:T:WEP;S:OldNetwork;P:legacypass;;

Open Network (No Password)

Format: T:nopass or T:

No password required. Omit the P parameter entirely.

WIFI:T:nopass;S:PublicWiFi;;

πŸ‘οΈ Hidden Networks (H Parameter)

The H parameter indicates whether the network hides its SSID broadcast.

Visible Network (Default):

WIFI:T:WPA;S:MyNetwork;P:password123;;
// H parameter omitted = visible network

Hidden Network:

WIFI:T:WPA;S:HiddenNetwork;P:password123;H:true;;
// H:true = network doesn't broadcast SSID

⚠️ Note: Hidden networks provide minimal security benefit and can cause connection issues. Most security experts recommend visible SSIDs with strong passwords instead.

πŸ’» Implementation Examples

JavaScript / TypeScript

function generateWiFiQRString(
  ssid: string,
  password: string,
  authType: 'WPA' | 'WEP' | 'nopass' = 'WPA',
  hidden: boolean = false
): string {
  // Escape special characters
  const escape = (str: string): string => {
    return str
      .replace(/\\/g, '\\\\')  // Backslash first!
      .replace(/;/g, '\\;')
      .replace(/:/g, '\\:')
      .replace(/,/g, '\\,')
      .replace(/"/g, '\\"');
  };

  const escapedSSID = escape(ssid);
  const escapedPassword = escape(password);

  // Build WiFi string
  let wifiString = `WIFI:T:${authType};S:${escapedSSID};`;

  if (authType !== 'nopass' && password) {
    wifiString += `P:${escapedPassword};`;
  }

  if (hidden) {
    wifiString += 'H:true;';
  }

  wifiString += ';'; // Terminator

  return wifiString;
}

// Usage
const qrData = generateWiFiQRString(
  'My;Network',
  'Pass:word123',
  'WPA',
  false
);
// Result: WIFI:T:WPA;S:My\;Network;P:Pass\:word123;;

Python

def generate_wifi_qr_string(
    ssid: str,
    password: str,
    auth_type: str = "WPA",
    hidden: bool = False
) -> str:
    """Generate WiFi QR code string."""

    # Escape special characters
    def escape(text: str) -> str:
        return (text
            .replace("\\", "\\\\")  # Backslash first!
            .replace(";", "\\;")
            .replace(":", "\\:")
            .replace(",", "\\,")
            .replace('"', '\\"'))

    escaped_ssid = escape(ssid)
    escaped_password = escape(password)

    # Build WiFi string
    wifi_string = f"WIFI:T:{auth_type};S:{escaped_ssid};"

    if auth_type != "nopass" and password:
        wifi_string += f"P:{escaped_password};"

    if hidden:
        wifi_string += "H:true;"

    wifi_string += ";"  # Terminator

    return wifi_string

# Usage
qr_data = generate_wifi_qr_string(
    ssid="My;Network",
    password="Pass:word123",
    auth_type="WPA",
    hidden=False
)
# Result: WIFI:T:WPA;S:My\;Network;P:Pass\:word123;;

PHP

function generateWiFiQRString(
    string $ssid,
    string $password,
    string $authType = 'WPA',
    bool $hidden = false
): string {
    // Escape special characters
    $escape = function(string $str): string {
        return str_replace(
            ['\\', ';', ':', ',', '"'],
            ['\\\\', '\\;', '\\:', '\\,', '\\"'],
            $str
        );
    };

    $escapedSSID = $escape($ssid);
    $escapedPassword = $escape($password);

    // Build WiFi string
    $wifiString = "WIFI:T:{$authType};S:{$escapedSSID};";

    if ($authType !== 'nopass' && !empty($password)) {
        $wifiString .= "P:{$escapedPassword};";
    }

    if ($hidden) {
        $wifiString .= 'H:true;';
    }

    $wifiString .= ';'; // Terminator

    return $wifiString;
}

// Usage
$qrData = generateWiFiQRString(
    'My;Network',
    'Pass:word123',
    'WPA',
    false
);
// Result: WIFI:T:WPA;S:My\;Network;P:Pass\:word123;;

πŸ“± QR Code Generation Parameters

After generating the WiFi string, you need to encode it into a QR code image. Key parameters:

Error Correction Level

QR codes support four error correction levels. Higher levels allow the code to be scanned even if partially damaged.

  • L (Low): ~7% recovery - Smallest QR code, use for digital displays
  • M (Medium): ~15% recovery - Recommended for most use cases
  • Q (Quartile): ~25% recovery - Good for printed materials that may get worn
  • H (High): ~30% recovery - Best for outdoor/high-wear applications

QR Code Size

Recommended sizes based on use case:

  • 256px: Small cards, digital displays
  • 512px: Standard printing (business card size)
  • 1024px: Large prints, posters (recommended for most physical uses)
  • 2048px: Very large prints, banners

Quiet Zone (Margin)

QR codes require white space around them (called "quiet zone"). Minimum of 4 modules (4x the size of one QR code square). Without proper quiet zone, scanners may fail to detect the code.

πŸ“± Device Compatibility

βœ… Native Support (No App Required)

  • βœ“iOS 11+ (iPhone, iPad) - Built into Camera app
  • βœ“Android 10+ - Built into Camera app
  • βœ“Android 9 (Pie) - Some manufacturers (Samsung, Google Pixel)

⚠️ Requires QR Scanner App

  • β€’iOS 10 and below
  • β€’Android 8 and below
  • β€’Older Android devices without manufacturer camera enhancements

πŸ’‘ Best practice: Include the written SSID and password as backup text on printed materials for users with older devices.

🚨 Common Implementation Pitfalls

❌ Missing Escape Sequences

Failing to escape special characters in SSID or password will break the QR code.

// WRONG - semicolon not escaped

WIFI:T:WPA;S:Coffee;Shop;P:password;;

// CORRECT - semicolon escaped

WIFI:T:WPA;S:Coffee\;Shop;P:password;;

❌ Wrong Escape Order

Always escape backslashes FIRST, or you'll double-escape other characters.

// WRONG - escapes ; first, then \

str.replace(/;/g, '\\;').replace(/\\/g, '\\\\')

Result: "a;b" becomes "a\\\;b" (incorrect!)

// CORRECT - escapes \ first

str.replace(/\\/g, '\\\\').replace(/;/g, '\\;')

Result: "a;b" becomes "a\;b" (correct!)

❌ Missing Double Semicolon Terminator

Format MUST end with ;; (two semicolons).

// WRONG - single semicolon

WIFI:T:WPA;S:Network;P:pass;

// CORRECT - double semicolon

WIFI:T:WPA;S:Network;P:pass;;

❌ Case Sensitivity

The protocol identifier "WIFI:" is case-sensitive. Must be uppercase.

// WRONG - lowercase

wifi:T:WPA;S:Network;P:pass;;

// CORRECT - uppercase WIFI

WIFI:T:WPA;S:Network;P:pass;;

❌ Incorrect QR Code Type

Generate as a standard text QR code, not a URL or specialized format. The string should be encoded as plain text.

βœ… Testing Your Implementation

Testing Checklist:

Test with special characters: SSID and password containing ; : , " \
Test all auth types: WPA, WPA2, WEP, open network
Test hidden networks: With and without H:true parameter
Test device compatibility: iOS, Android, older devices
Test QR code size: Verify minimum size for reliable scanning
Test quiet zone: Ensure adequate white space margin
Test error correction: Verify code still works when partially obscured

πŸ’‘ Quick validation: Use our WiFi QR Code Generator to generate reference QR codes and compare your output.

Need a Reference Implementation?

Try our generator to see correctly formatted WiFi QR codes

Try the Generator β†’