Open software for the Sony HAP-Z1ES and HAP-S1.
Sony shipped a 2014 audiophile masterpiece, then stopped writing software for it in January 2021. The hardware still sings. This is the rest of the story.
Download HAP Sync · I own a HAP · How it works · Documentation
Six things your player can do again, over your own network, with nothing sent anywhere. Nothing here can damage the device: reads are pure, playback is bounded, and standby asks first.
The first four work the moment you run them. The last two need a one-off scan of your library first — it is slow, and this page says so where it happens rather than letting you find out.
Sony's only supported route is an SMBv1 share. Modern Windows and macOS resist it, and when it half-works it drops files without saying so.
HAP Sync speaks the protocol itself, so your operating system keeps its defences up. Point it at a folder, press Sync. It finds the player, wakes it if asleep, transfers only what changed, and skips the junk that becomes ghost tracks. Libraries stuck for years transfer cleanly.
Double-click
HapSync.exe. No Python, no account, no configuration file to edit.
python tools/webui.py <hap-ip> # then open http://localhost:8080Now-playing with cover art, transport, seek, the sound settings, six languages, light and dark. Updates arrive the instant the music changes, because the player pushes them.
It also shows the player's own front panel, live, with its buttons — so everything Sony left in the on-device menus but took out of the app is reachable from the sofa. Including playing a whole album, which none of the APIs can do.
On an iPhone: Safari → Share → Add to Home Screen gives a standalone remote with its own icon. No App Store. How to install it.
It was never broken. Sony removed it from the mobile app and from the front-panel menus — not from the machine.
python tools/hap_client.py <hap-ip> radio-browse root
python tools/hap_client.py <hap-ip> play-station --uri <uri>It took this project five days and three published-then-retracted theories to discover we were sending one HTTP header too many. The whole story.
The player's own library API answers over the network — artists, albums, tracks with codec and sample rate, one tap to play. This is the half Sony's app lost, and browsing works straight away:
python tools/hap_library.py <hap-ip> artists
python tools/hap_library.py <hap-ip> album-tracks 10633Drilling into an artist or an album is instant. A top-level listing is not: the player counts its
entire catalogue before answering, so the first artists can take a minute. It is then cached.
These two need a copy of your catalogue first, and taking it is slow. The player answers one request at a time and charges for counting the whole table, so a full read of a 78 000-track library took 92 minutes. Once. After that everything below is instant, and the copy is kept on your machine.
python tools/hap_library.py <hap-ip> harvest # once. Go and do something else.Then search — accent-insensitive, so dvorak finds Dvořák:
python tools/hap_library.py <hap-ip> search dvorakAnd the audiophile health check: how much of your library is genuinely hi-res versus CD versus lossy, DSD and at what rates, PCM above the player's 192 kHz ceiling, albums showing a blank tile for want of artwork, duplicated tracks.
python tools/library_audit.py --from-player <hap-ip>Fix takes those findings and tells you where each album actually is — then opens it in Explorer or a tag editor. If the album is also on your own disk it opens your copy, so the edit is instant and your next sync carries it to the player.
It needs one more scan, of the player's file shares — about four minutes, and the Index the shares button in HAP Sync does it for you:
python tools/hap_fixit.py <hap-ip> index # ~4 min, once
python tools/hap_fixit.py <hap-ip> reportWindows, no Python. Download HapSync.exe,
put it anywhere, double-click it. On first launch SmartScreen asks — More info, then Run anyway.
It isn't code-signed yet.
Everything else. Python 3.10 or newer:
git clone https://github.com/Guillain-RDCDE/HAP-Revival.git
cd HAP-Revival
python tools/discover.py # find the HAP on your network
python tools/webui.py <hap-ip> # browser remote, on port 8080
python tools/hap_client.py <hap-ip> now-playing # or the command line
python tools/webui.py --demo # no HAP? drive the mock device insteadOnly the SMB tools need a dependency — pip install pysmb. Everything else is standard library.
To build the .exe yourself, run tools/build_gui.ps1 in a clean virtual environment.
No player yet? mock_hap.py impersonates one faithfully — a living demo
library, generated cover art, working transport, the REST catalogue, and the front panel with its
keys. The remote, the client, the library tools and the screen tool all run against it; only the
live smoke test needs real hardware, since checking a real player is the entire point of it.
The rest of this page is for people who want to know how, and why it is trustworthy.
Dual Burr-Brown PCM1795 DACs, an Analog Devices SHARC DSP, a custom FPGA on the clock domain, an isolated linear supply, fourteen kilos of chassis — and, underneath, an i.MX6 running Linux 3.0.35 with Samba 3.0.37. A decade on it still measures and sounds superb. The software is what rotted: SMBv1 transfers, standard-resolution Spotify on a hi-res deck, nothing added since 2016.
The analog chain — FPGA → SHARC → PCM1795 — is the entire point of this hardware. Every phase of this project leaves it untouched.
Port 60200 serves three distinct interfaces. The third exists in no public documentation.
| Interface | Shape | What it gives |
|---|---|---|
| ScalarWebAPI | JSON-RPC | Transport, now-playing, sound settings, internet radio. ~30 methods validated live, with a machine-readable spec |
REST /sony/contentplayer + /sony/contentdb |
REST | Power, transport, and the whole music catalogue — artists, albums, tracks, codecs, artwork |
/sony/hap |
Query-string GET | The front panel as a PNG, and its buttons injectable. Found only in two "out of support" pages the player still serves |
Plus a UDP push channel: the player announces state changes instead of needing to be polled.
Full map: docs/03-network-api.md. The first two came out of a
teardown of Crestron's 2016 control module;
the third came from a contributor noticing two file names.
Nothing published so far has opened a case or touched firmware. The writes made are the ordinary ones a remote control makes.
- The front panel is mirrorable and scriptable over HTTP. Fetch the 480×272 display as a PNG,
press its keys:
python tools/hap_screen.py <ip> show(write-up). Everything Sony left in the on-device menus is reachable from the network — no firmware, no UART, no NAND. - The library API was never dead — the finding that reshaped the project. It answers fine; it is simply slow, and every tool here had a six-second timeout (measurements).
- Internet radio works, and always did.
- Sony's
HDDAudioRemoteAndroid app is decompiled — the first public decompile of this client. - The internal disk is read. It holds no operating system: a SQLite catalogue and your music, with the full schema in hand.
- The hardware is identified from the metal up, including both DSPs and the kernel driver's ioctl surface.
- Sony's update host is alive and is a plain HTTP file server, so the firmware image may be
downloadable rather than needing a NAND dump (
docs/07-firmware.md).
This is a 2014 embedded box with a 2014 HTTP stack, and it punishes several habits that are correct
everywhere else. docs/16-gotchas.md is nine of them, each a case where
the generally right move is the locally wrong one:
- Setting
Content-Typeon a JSON POST from a browser breaks the request. - Issuing requests concurrently poisons unrelated endpoints — the daemon serialises.
- A short HTTP timeout reads as a dead API. Cold library requests took 5 to 57 seconds here — and that figure is a property of the catalogue's size, not of the device, so it is a floor, not a number. Double the deadline on retry rather than picking a ceiling.
- Response bodies are not uniformly UTF-8: one artist name in 17 317 arrived as raw Latin-1
inside otherwise valid UTF-8, and
json.loadslost the whole 343 KB page over one character. - Reusing one SMB connection across two long listings silently returned 5 931 files instead of 66 733, with no error at all.
If you are writing a client for this player, read that page before you write anything else.
Measure, publish, and correct in public. Six conclusions published here have since been overturned — five by a contributor who owns the hardware, one by our own testing — and each correction is written up next to the claim it replaces rather than quietly edited away.
The most expensive of them: a "dead" API that was merely slow, believed for months because every tool gave up after six seconds. The lesson generalised in gotcha 7: a failure that always arrives at the value you chose is evidence about your client, not about the device.
300 tests, stdlib-only, run against a mock device on every push, plus a live smoke test that asserts real values from a real player — because green unit tests once passed against a client that read nothing at all.
Five phases: reverse engineering → a modern control app over the existing API → a root shell → a custom userland keeping Sony's kernel and audio driver → a modern OS. Risk to the device stays at none until phase three, and the custom userland waits behind a tested recovery path.
HAP-Z1ES. The primary target. A pure source player with clean analog out and no internal amp.
HAP-S1. The smaller sibling, with an integrated amp. Same SoC, same firmware images, same protocols — work on one transfers to the other.
Nineteen of them. Stdlib-only Python, no accounts, no telemetry.
Full list
- HAP Sync — copies your music to the HAP in one click. Start here.
- HAP Sync CLI — the same transfer engine, scriptable.
- SMB Doctor — repairs the Windows settings that updates keep breaking.
- Companion — pre-flight validation and a library diff for any copy tool.
- Web UI — now playing, transport, sound settings, library browse and search.
- Control app — the same UI on your phone's home screen.
- Python client — every mapped API method, including internet radio.
- Front panel — mirror the display, press its keys, over HTTP.
- Push notifications — the player says when something changes.
- Discovery — finds the HAP on your network.
- Library over REST — the whole catalogue from a running player.
- Library audit — formats, hi-res share, duplicates, missing artwork.
- Fix it — every finding with the real folder it is in, ready to open.
- Library browser — reads the on-disk catalogue offline.
- Mock device — a fake HAP that answers the real protocol.
- Live smoke test — checks the client against your own player.
- Interceptor — logs what names the player looks up.
- API fuzzer and call — probe the API by hand.
- Link checker — every relative link and heading anchor. Runs in CI.
New here? Start Here. The project in one page: Overview. Own a HAP and want to help? Help in five minutes — read-only, copy-paste, no Python needed.
Full index — hardware, API, disk, firmware, UART, audio path
| Hardware | Software stack | Network API | SMB share |
| Diag modes | HDD swap | Firmware | Prior art |
| Disk layout | UART console | Audio path | Music sync |
| Control app | NAND extraction | Forza ioctl | Gotchas |
Reconnaissance notes live in research/, the tools in tools/, the API
specification in api-spec/.
The single most useful thing you can do is run one command against your own player and paste what it prints. Every significant finding here came from that, not from deeper analysis in isolation — including one from a contributor who simply noticed two file names.
Help in five minutes has read-only commands that need no Python.
CONTRIBUTING.md says which machine can answer which question — an
HAP-S1, an older firmware and a second region's TuneIn tree all answer things a HAP-Z1ES cannot.
Corrections are as welcome as findings. Several claims on these pages were wrong until somebody who owned the hardware said so.
Code is MIT. Documentation and research notes are CC BY 4.0. Not affiliated with Sony.
Amos, who in one week contributed the Crestron module, measurements from a HAP-S1 this project does not own, a firmware version nobody had recorded, and the two file names that led to the front panel API. Saschko, for a second region's TuneIn tree. And the HAP owners on the Steve Hoffman forums whose posts made several of these threads findable at all.

