Accessibilibounty Hunters
A cartoon bounty hunter with a huge handlebar mustache, sunglasses on his head, a sleeveless leather vest and a "VoiceOver" heart tattoo squints through a magnifying glass at an iPhone, where a nervous bug hides behind a button. A WANTED poster for The Unlabeled Button, a smug blank button in a cowboy hat saying "Button. Button. Button." Last seen confusing VoiceOver users. Reward: 1,000 points.

Accessibilibounty Hunters

accessibility + bounty hunters say it “access-i-bill-i-bounty hunters”

It's a bug bounty, but for accessibility bugs. Find them, report them and earn prizes.

How bounty hunting works

A burly cartoon bounty hunter with goggles and an accessibility tattoo rides a motorcycle with one hand and swings a butterfly net with the other, chasing a panicking bug that holds a "Tap target too small" sign.
  1. Pick an app Any iOS app on the App Store counts, whether it runs on iPhone or iPad. The apps listed below are a good place to start. Try it with the accessibility features you know: VoiceOver, Voice Control, larger text, keyboard, and so on.
  2. Report what you find Email your bug to hello@robinkanatzar.com. Say what happened, what you expected and how to make it happen again.
  3. Get verified Every report is checked by hand. If something is unclear, you'll get an email asking about it.
  4. Climb the board Verified bugs earn points. The more you find, the higher you go. The top hunter wins the first prize.

What makes a good report

  • The app's name and version, and your device (iPhone or iPad) and iOS version.
  • The accessibility feature or setting you were using.
  • The screen you were on and the steps that led to the bug.
  • What happened, and what you expected to happen instead.
  • A screenshot or screen recording, if you can make one.
  • The name you'd like to show on the leaderboard.

Apps on the hunt list

Have an iOS app? Get it listed.

Leaderboard

The Accessibilibounty Hunters with the most points will be listed here, top scorer first. The board is empty for now, so the first hunter to report a verified bug takes the top spot.

First prize

A temporary tattoo on a person's upper arm: a red heart wrapped in a banner that reads "VoiceOver".

The top hunter on the leaderboard wins a VoiceOver temporary tattoo: the red heart with the "VoiceOver" banner, just like the one on our bounty hunter's arm.

The tattoo washes off. The glory of being number 1 doesn't.

More prizes are coming soon.

For developers

If you want the community to find accessibility bugs in your iOS app, get it listed here.

What you get

  • Every bug report is checked to make sure it's real before it reaches you.
  • Anything unclear gets sorted out with the person who reported it.
  • You get one short, friendly email with the bugs to fix, plus tips and help on how to fix each one. No vague to-do list.

Add a report button to your app

The best bug reports come from people using your app every day. Add a "Report an Accessibility Issue" button to your settings screen. It opens an email to Accessibilibounty Hunters, filled in with your app's details and the accessibility settings the person has turned on.

1. Copy the button into your SwiftUI project

Change appName and appStoreLink to match your app.

ReportAccessibilityIssueButton.swift
import SwiftUI
import UIKit

/// Opens a pre-filled email to report an accessibility bug.
/// Change appName and appStoreLink, then add
/// ReportAccessibilityIssueButton() to your settings screen.
struct ReportAccessibilityIssueButton: View {
    // Change these to match your app
    private let appName = "My Indie App"
    private let appStoreLink = "https://apps.apple.com/app/id0000000000"

    // Reports go to Accessibilibounty Hunters
    private let reportAddress = "hello@robinkanatzar.com"

    @Environment(\.openURL) private var openURL
    @Environment(\.dynamicTypeSize) private var dynamicTypeSize
    @State private var showNoMailAlert = false

    var body: some View {
        Button {
            guard let url = reportURL else { return }
            openURL(url) { opened in
                if !opened { showNoMailAlert = true }
            }
        } label: {
            Label("Report an Accessibility Issue", systemImage: "accessibility")
        }
        .alert("No Mail App Found", isPresented: $showNoMailAlert) {
            Button("Copy Email Address") {
                UIPasteboard.general.string = reportAddress
            }
            Button("OK", role: .cancel) { }
        } message: {
            Text("Please email your report to \(reportAddress).")
        }
    }

    private var reportURL: URL? {
        let subject = "Accessibility bug: \(appName)"
        return URL(string: "mailto:\(reportAddress)?subject=\(encode(subject))&body=\(encode(emailBody))")
    }

    private var emailBody: String {
        let info = Bundle.main.infoDictionary
        let version = info?["CFBundleShortVersionString"] as? String ?? "unknown"
        let build = info?["CFBundleVersion"] as? String ?? "unknown"
        let device = UIDevice.current

        return """
        What happened?


        What did you expect to happen?


        Steps to reproduce (which screen, what you tapped):


        ---
        Please keep the details below. They help check the bug.
        App: \(appName) \(version) (\(build))
        App Store: \(appStoreLink)
        Device: \(device.model), \(device.systemName) \(device.systemVersion)
        VoiceOver: \(onOff(UIAccessibility.isVoiceOverRunning))
        Switch Control: \(onOff(UIAccessibility.isSwitchControlRunning))
        Text size: \(String(describing: dynamicTypeSize))
        Bold Text: \(onOff(UIAccessibility.isBoldTextEnabled))
        Increase Contrast: \(onOff(UIAccessibility.isDarkerSystemColorsEnabled))
        Reduce Motion: \(onOff(UIAccessibility.isReduceMotionEnabled))
        Reduce Transparency: \(onOff(UIAccessibility.isReduceTransparencyEnabled))
        """
    }

    private func onOff(_ isOn: Bool) -> String {
        isOn ? "On" : "Off"
    }

    private func encode(_ text: String) -> String {
        let unreserved = CharacterSet(charactersIn:
            "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~")
        return text.addingPercentEncoding(withAllowedCharacters: unreserved) ?? text
    }
}

2. Add it to your settings screen

SettingsView.swift
Form {
    Section("Support") {
        ReportAccessibilityIssueButton()
    }
}

Good to know

  • The email lists VoiceOver, Switch Control, text size, Bold Text, Increase Contrast, Reduce Motion and Reduce Transparency. iOS doesn't let apps detect Voice Control or Full Keyboard Access, so people can mention those themselves.
  • If no mail app is set up on the device, the button shows the email address and offers to copy it.
  • Want reports to come to you as well? Add your own address after a comma in reportAddress, or send an email to talk about it.

Frequently asked questions

Who reviews the accessibility bugs?

Me, Robin Kanatzar: iOS engineer and accessibility geek. If a bug goes beyond what I know, I'll call in experts.

What kind of apps can I find bugs in?

Only iOS apps for now, on iPhone or iPad. Maybe later we'll expand to macOS, visionOS and other platforms.

How do I know what counts as an accessibility bug?

Read Apple's Human Interface Guidelines on accessibility. They're the best place to start learning what to look for.

Why do I need the community to help? Why can't I just use AI?

AI is fast and keeps getting better, but the community will always find better usability bugs. People who use VoiceOver, Voice Control or larger text every day notice what makes an app hard to use, not just what breaks a rule. Besides, it'll save you tokens.