# Web Bluetooth on iPhone finally works

For years the answer to "can I use Web Bluetooth on iPhone?" was a short, unhappy no. Safari did not — and still does not — implement the W3C Web Bluetooth specification. The standard response was to ship a native iOS app (Cordova, Capacitor, React Native, Flutter) or to give up on the iOS half of your audience. WebBLE changes that. This post explains what WebBLE actually is, why it works inside Apple's rules, and what it costs.

## The problem in one paragraph

`navigator.bluetooth` is a W3C working draft shipped by Chrome, Edge, and Opera. Safari has declined to implement it citing privacy and security concerns, and iOS enforces WebKit as the rendering engine for every browser on the platform, so no third-party iOS browser can ship the API either. The net effect: if your product is a web page and you want to talk to a Bluetooth Low Energy device on an iPhone, there is no web-native path. You have to leave the web.

## What WebBLE is

WebBLE is a **Safari Web Extension**, distributed through the iOS App Store, that polyfills the W3C `navigator.bluetooth` API inside the user's own Safari. Once the user installs the extension and grants it permission on a website, that website's JavaScript can call `navigator.bluetooth.requestDevice`, `GATTServer.connect`, `characteristic.readValue`, and the rest of the standard surface, and the calls reach real CoreBluetooth through the extension's native handler.

The site code is unchanged. It is the same `navigator.bluetooth` code that already runs on Chrome desktop. There is no SDK to import, no rewrite, no platform fork.

## Why this is allowed

Safari Web Extensions are a first-class, documented Apple feature. They ship as containers through the App Store, go through normal App Review, and a user opts in by installing the extension and granting per-site permission. WebBLE is not a jailbreak, not an enterprise cert workaround, and not a private API hack. The native side uses public CoreBluetooth; the web side is a standard polyfill.

## How it fits into an existing web app

Three lines.

```html
<script src="https://cdn.ioswebble.com/v1.js" defer></script>
```

Then write the same `navigator.bluetooth` code you would write for Chrome:

```js
const device = await navigator.bluetooth.requestDevice({
  filters: [{ services: ['heart_rate'] }]
});
const server = await device.gatt.connect();
const service = await server.getPrimaryService('heart_rate');
const chr = await service.getCharacteristic('heart_rate_measurement');
await chr.startNotifications();
chr.addEventListener('characteristicvaluechanged', (e) => {
  console.log('BPM:', e.target.value.getUint8(1));
});
```

On Chrome this hits the browser's native implementation. On iOS Safari with WebBLE installed it hits the extension. There is no `if (iOS)` branch in your code.

## What it costs

The polyfill is free for `navigator.bluetooth`. Premium capabilities are exposed under `window.webbleIOS` and are billed separately:

- **Background Sync** — keep a GATT connection alive and fire iOS notifications when a characteristic changes, even with Safari closed.
- **Beacons** — scan for advertising packets matching service-UUID filters in the background.
- **Peripheral** — advertise the iPhone itself as a BLE peripheral.
- **White-label** — ship a branded companion app.

See [premium](../premium.md) for the exact API surface.

## What it does not do

WebBLE cannot magically circumvent the W3C permission model. `requestDevice` still triggers the iOS system chooser; you cannot silently enumerate devices. The site still needs HTTPS. User gestures are still required. The rules are the W3C rules.

## When to pick WebBLE

- Your product is a web page (PWA, SaaS console, dashboard, marketing site with a demo).
- You already use `navigator.bluetooth` on Chrome and want iOS parity without porting.
- You want same-day deploys, no App Review loop of your own.
- You need BLE on iPhone without making your product a native app.

## When not to pick WebBLE

- Your product must be a native app for non-BLE reasons (deep HealthKit, CarPlay, widgets).
- You cannot ask users to install an extension, even once.

## Next steps

- Read the [quickstart](../quickstart.md).
- Browse the [recipes](../recipes.md) — heart rate, battery, CGM, lock, beacon.
- Ask whether it [supports your framework](../is-web-bluetooth-supported-in-safari.md).
