BLE Advertising Packets Explained: How Devices Broadcast Without Connecting
Before any BLE device connects, it broadcasts. A temperature sensor, a beacon, a heart-rate strap, an industrial vibration monitor — every one of them sends advertising packets so nearby scanners can find it. This is the layer where device discovery actually happens, and it is also the layer where most "why can't I see my device" debugging lives.
This guide decodes a BLE advertising packet byte by byte: the PDU header, the 31-byte payload limit, Advertising Data (AD) structures, and the flags, UUIDs, and manufacturer data that fill them. You'll learn how to read raw advertising data in hex — and how to do it on macOS without a Windows-only vendor tool.
Advertising vs Connecting: Two Separate Channels
BLE separates discovery from communication. A device alternates between two roles over the same radio:
- Advertising — the device broadcasts a small packet on a fixed schedule so scanners can find it. No connection is established.
- Connecting — after a scanner initiates, both sides switch to a private data channel and exchange full GATT traffic.
The advertising channel is what makes BLE "findable." A beacon like an iBeacon or Eddystone never connects at all — its entire job is broadcasting advertising packets forever.
This is why a BLE scanner shows dozens of devices you've never paired with: every device in range is advertising, and the scanner is just listening.
The Advertising Packet Structure
A BLE advertising packet on the air has two parts: a PDU (Protocol Data Unit) and the CRC that follows it. The PDU contains a 2-byte header and the payload. For the most common type — ADV_IND (connectable, scannable advertising) — the payload is:
BLE Advertising Packet (ADV_IND)
┌──────────┬──────────┬───────────────────────┬──────────┐
│ PDU Type │ Length │ AdvA (6 bytes) │ AdvData │
│ (1 byte) │ (1 byte) │ advertiser address │ (0-31 B) │
└──────────┴──────────┴───────────────────────┴──────────┘
The PDU type nibble tells you the advertising kind:
| PDU Type | Meaning |
|---|---|
| 0x00 — ADV_IND | Connectable and scannable (most common) |
| 0x01 — ADV_DIRECT_IND | Directed at one specific device |
| 0x02 — ADV_NONCONN_IND | Non-connectable (beacons) |
| 0x03 — SCAN_REQ | Scanner asking for a scan response |
| 0x04 — SCAN_RSP | The scan response with extra data |
The length byte counts everything after it — the 6-byte address plus up to 31 bytes of advertising data. That 31-byte cap is the number that matters for what you can fit in a broadcast.
31 bytes is the limit: The entire AdvData field is capped at 31 bytes per packet. To broadcast more, a device uses a scan response (another 31 bytes) or moves to extended advertising in BLE 5 (up to 255 bytes per packet).
Advertising Data: AD Structures
AdvData is not one blob — it is a list of AD structures (Advertising Data structures). Each structure has a tiny header and a payload:
AD Structure
┌──────────┬──────────────┬──────────────┐
│ Length │ AD Type │ Data │
│ (1 byte) │ (1 byte) │ (Length-1 B) │
└──────────┴──────────────┴──────────────┘
The Length byte includes the AD Type byte but not itself. So 02 01 06 means: 2 bytes follow, type 0x01 (Flags), one byte of flags data (0x06).
Here are the AD types you will actually see in the wild:
| AD Type | Name | Example |
|---|---|---|
| 0x01 | Flags | 02 01 06 — LE General Discoverable |
| 0x02 / 0x03 | Incomplete / Complete list of 16-bit UUIDs | 03 02 0A 18 — Heart Rate Service |
| 0x06 / 0x07 | Incomplete / Complete list of 128-bit UUIDs | Custom service UUIDs |
| 0x08 / 0x09 | Short / Complete local name | 0A 09 54 65 6D 70 53 65 6E 73 6F 72 |
| 0xFF | Manufacturer Specific Data | 05 FF 4C 00 02 15 — Apple iBeacon prefix |
| 0x16 | Service Data | 16-bit service UUID + its data |
| 0x1A / 0x1B | LE Bluetooth Device Address | Public/random address |
| 0x0A | Tx Power Level | RSSI calibration for distance |
Decoding a Real Packet Byte by Byte
Here is a complete, real-world advertising packet from a BLE temperature sensor. This is exactly what a scanner reports as raw hex:
04 3E 2B 02 01 03 01 9B 0A B0 68 91 02 1A 02 01 06
11 07 11 0C C9 4F 65 7A 4E 46 66 4E D2 8B B7 7C 0A FF
4C 00 10 05 03 64 0D 02 02 03 04
Let's split the AdvData AD structures:
02 01 06 → Flags: LE General Discoverable
11 07 11 0C C9 4F 65 7A 4E 46 66 4E D2 8B B7 7C
→ 128-bit service UUID (16 bytes):
4F 65 7A 4E 46 66 4E D2 8B B7 7C 11 0C C9 ... reversed
0A FF 4C 00 10 05 03 64 0D 02 02 03 04
→ Manufacturer data (Apple 0x004C)
Walking through the AD structures:
02 01 06— 2 bytes follow, type 0x01 (Flags), value 0x06 = LE General Discoverable + BR/EDR not supported.11 07— 17 bytes follow, type 0x07 = Complete list of 128-bit service UUIDs. The next 16 bytes are the UUID, transmitted least-significant byte first, so you reverse them to read the real UUID.0A FF 4C 00— 10 bytes follow, type 0xFF = Manufacturer Specific Data, Company ID 0x004C (Apple). The rest is the vendor's own layout.
The first two bytes of the whole packet (04 3E) are the HCI event header from the Bluetooth controller — a "LE Meta Event" carrying an advertising report. Every scanner tool shows these differently, but the AD structures are always there once you find the AdvData field.
Key skill: if you can find the first AD structure (Length + Type) in a hex dump, you can decode the rest mechanically — each Length tells you exactly where the next structure begins. No protocol wizardry required.
Why the Local Name Is Often Missing
You scan, you see a device, but there's no name — only a MAC-like address. That is normal. Two reasons:
- The name lives in the scan response. Many devices send a minimal ADV_IND with flags + UUIDs, then provide the name only when a scanner sends a SCAN_REQ. Passive scanners that never send SCAN_REQ won't see the name.
- The name is too long. "Temperature_Sensor_Kitchen_01" is 27 bytes — it fits alone, but not alongside UUIDs and manufacturer data in 31 bytes. So the device sends a short name (AD type 0x08) in the packet and the full name in the scan response.
This is why your scanner shows "unknown" for a lot of devices: they are advertising without a name, or the scanner didn't request the scan response.
Advertising Interval, Duty Cycle, and Battery Life
Advertising costs battery, and the interval controls how much. The BLE spec allows 20 ms to 10.24 s between advertising events. Common choices:
| Interval | Use case | Trade-off |
|---|---|---|
| 20–100 ms | Fast discovery, user-initiated pairing | Battery drains noticeably |
| 100–500 ms | Interactive devices, HID | Good balance |
| 1–2 s | Industrial sensors, beacons | Discovery takes longer |
| 5–10 s | Coin-cell beacons, long-life trackers | Slow to find, but years of battery |
A coin-cell beacon advertising at 1 Hz typically runs for 1–3 years. The same beacon at 20 ms would die in weeks. If you're tuning a sensor deployment, advertising interval is the single biggest battery lever you have.
How to Decode Advertising Packets on macOS
You don't need a Windows machine or a proprietary sniffer to read advertising data. On macOS:
- Use a BLE scanner that shows raw advertising data. A native GATT browser like BLE Inspector for macOS reports each advertising report with its raw hex alongside the parsed AD structures — flags, UUIDs, manufacturer data, and name.
- Cross-check with a second source. macOS's built-in
bluetoothdlog, or a cheap USB BLE dongle, can confirm what you're seeing on the wire. - Decode the hex by hand using the Length + Type structure walk above — useful when a vendor's payload isn't parsed by any tool yet.
For beacons specifically, the payload after the FF 4C 00 prefix (iBeacon) or the AA FE prefix (Eddystone) follows a fixed layout you can decode byte by byte.
Common Advertising Debugging Problems
Device Not Showing Up at All
If a device never appears in any scan, check:
- Advertising disabled — many devices advertise only while a button is held, or only after power-up for 30 seconds.
- Wrong PHY — BLE 5 devices advertising on the secondary (Coded/125 kbps) PHY won't be seen by older scanners.
- Directed advertising — a device doing ADV_DIRECT_IND only responds to its paired host.
Device Visible but Name "Unknown"
Request the scan response. A scanner that sends SCAN_REQ gets the extra 31 bytes where the name usually lives. If the name is still missing, the device simply doesn't advertise one.
Duplicate Reports Flooding the Scanner
Devices re-advertise on every interval. A good scanner deduplicates by address and only shows changes — but raw HCI logs will show the same device dozens of times per minute. That's normal.
RSSI is not distance: you can estimate rough proximity from signal strength, but walls, metal enclosures, and antenna orientation swing RSSI by 20+ dB. Treat "distance" from RSSI as a hint, not a measurement.
The Bottom Line
BLE advertising is how every wireless device makes itself findable: a 31-byte payload of AD structures — flags, UUIDs, name, and manufacturer data — broadcast on a schedule. Decoding it is mechanical once you know that every AD structure starts with a Length byte and a Type byte.
Most "device not found" problems trace back to the advertising layer: the device isn't advertising, the scanner isn't requesting the scan response, or the data you expect (the name) lives in a different packet than the one you're reading.
On macOS, a native BLE inspector that surfaces raw advertising data turns a frustrating hex-dump session into a five-minute check.
Decode BLE Advertising on macOS
BLE Inspector for macOS shows every advertising report with parsed AD structures and raw hex. Scan, inspect, and understand any BLE device without Windows tools.
Explore BLE Inspector →