返回部落格

Joe Hou

I built a macOS app called Roam FM. The idea is simple: spin a 3D globe, land on a random spot, and listen to whatever radio station is broadcasting there. The station data comes from Radio Browser, an open-source, community-driven directory that anyone can use for free.

When the code was done, I thought the hard part was over. It wasn't even close.

App Store rejection screenshot

After setting up my Apple Developer account (a story for another day), I submitted the first build, expecting a smooth ride to the App Store.

Apple sent back a rejection.

The reason was Guideline 5.2.3: my app provided "potential unauthorized access to third-party audio streams." They asked for written proof that I held all necessary rights or licenses for the content.

I was confused. Radio Browser is open-source. Its data is in the public domain. Stations voluntarily submit their stream URLs. Roam FM doesn't record, download, or store any audio. It just plays public streams in real time.

Apple didn't see it that way.

Back and forth with App Review

Over the next two weeks, I tried everything I could think of.

Round one: I explained Radio Browser's open-source nature, attached the official policy statement, and listed other App Store apps using the same data source. I got a template rejection.

Round two: I rewrote the explanation from scratch, quoted the public domain declaration in full, described exactly how the app works technically, and cited multiple precedents. This time the reply included one extra sentence: "While the website is from an open-source project, the page itself collects streaming services and cannot guarantee compliance. Documentation is still required."

Round three: I changed tactics. Instead of arguing "open-source means free to use," I put together a technical audit report, checking every stream URL in the app and confirming none had any authentication or DRM. I submitted it as an attachment. The reply was the same template rejection.

By this point, the picture was clear. Apple didn't want a technical explanation. They wanted licensing documents from every single station. For an app aggregating over 40,000 public radio stations worldwide, that's effectively impossible.

This wasn't a new problem. Back in 2020, an AppleTV radio app called The Bat Player went through almost the exact same thing: same guideline, same demand for licensing documents, same data source. It was eventually pulled from the store. Six years later, Apple's stance hasn't changed.

Asking fellow developers

Strict review policies are one thing. What's truly frustrating is how opaque the process feels. Same data source, same technical approach, yet some apps get through while others don't.

Since the rules weren't transparent, the most practical move was to ask people who'd already made it.

I found a list of apps using Radio Browser on its website, picked out a few that were live on the App Store, and emailed their developers explaining my situation.

Every reply I got was generous.

Rob, who built FrogRadio, said he'd hit the same wall years ago. He told the review team that the stream URLs were public, that Radio Browser's policy explicitly stated the data was free for everyone, and that stations submitted voluntarily. That argument worked for him, but he admitted it doesn't work for many others. His exact words: "Apple does not seem to want more radio apps."

Ian, who built Bedside Radio, went a step further and shared the full statement he'd submitted during his own review. He added that he worries about getting rejected again every time he pushes an update.

These replies were reassuring, but they also confirmed something: the same reasoning gets different outcomes for different people.

Thank you, Rob, Ian, and everyone else who replied. The spirit of mutual help among indie developers is very real.

Leaving the App Store behind

After several rounds, I decided to stop fighting. If the front door was closed, I'd find another way in.

What I actually needed boiled down to four things: distribution, updates, payments, and discovery.

For distribution and updates, I went with GitHub. The installer lives on Releases, and the app uses an open-source auto-update library called s1ntoneli/AppUpdater so users can check for new versions and update with one click. All of this is free. GitHub is incredibly friendly infrastructure for indie developers. And without a review process, shipping becomes much faster: push the code, and it's live.

For payments, I chose Gumroad. After looking at several options, it was the simplest setup that didn't require running my own server. Users buy a license key and activate it in the app. It's rougher than in-app purchases, but it has upsides: I get the buyer's email for future communication, and payouts come weekly.

Discovery was the biggest shift. Without App Store search and recommendations, every user has to find the app on their own. That means I'm fully responsible for all traffic, and I have to think seriously about how to get the product in front of people. In a way, that's a good thing. It means I can't just toss the app into a store and hope for the best.

Looking back

Walking away from the App Store wasn't an easy call. For a new app, the App Store means trust. It means people can search for you, pay with one tap, and never worry about whether the download source is safe. Independent distribution can't easily replace that.

It also meant letting go of my original plan to go multi-platform. I always thought Roam FM would feel best on an iPad, like a real global radio with a globe you can hold in your hands. That's a small regret.

But things have to keep moving. Roam FM is alive and well. It's just not in the App Store.