How Bluesky’s iOS app makes its logo appear only in screenshots
A screenshot that refuses to match reality
There’s a special kind of confusing moment in mobile apps: you look at the screen, everything feels normal… and then a screenshot shows something different.
That’s what prompted the investigation behind Bluesky’s behavior. In the live app, the top-right area of a post thread looks like you’d expect (for example, a “Follow” button). But in screenshots taken in the same place, a small Bluesky logo watermark appears instead.
So how can an image capture the screen in a state that wasn’t visibly there a second earlier? The answer turns out to be one of those “modern apps meet old platform quirks” stories—specifically, a clever (and controversial) use of iOS’s handling of secure text fields.
The key idea: secure text rendering
On iOS, there’s a UIKit property called isSecureTextEntry on UITextField. A text field is the standard UI control for entering text; secure text entry is a mode usually meant for passwords. When isSecureTextEntry is enabled, iOS treats the content as sensitive: it obscures it in the UI and also takes steps to prevent capturing it in certain ways. Apple’s own documentation describes that secure text entry can hide the text and affect recording/screenshot behavior.
That is the official contract.
What Bluesky and other apps do is use a side-effect: they rely on iOS’s secure rendering path to change how parts of the view hierarchy get composed (combined into the final screen image), especially during screenshot capture.
And this is exactly where things get tricky to reason about: you’re not “calling an anti-screenshot API.” You’re piggybacking on how the system internally renders secure fields.
How a secure field becomes a screenshot mask
The technique used by Bluesky relies on a React Native / Expo package called expo-privacy-sensitive (by mozzius). The package’s job is to let a React component be marked as “privacy sensitive” on iOS, without needing app-specific UIKit code.
At a high level, the package works like this:
- It creates an off-to-the-side
UITextFieldwithisSecureTextEntry = true. - It moves the real content (in this case, the piece you want to disappear from screenshots) into the secure field’s internal rendering layer.
- When a screenshot is taken, iOS blanks out that secure rendering layer.
That blanking step is the “magic” moment. The screenshot doesn’t include the secure-field layer contents, even though those contents were visible on the live screen.
So instead of hiding the logo during normal rendering, Bluesky hides the button that sits above the logo.
Why the logo shows up in screenshots
Here’s the visual logic that makes the effect feel like a switcheroo:
- On the live screen, the UI is stacked so that the Follow button covers (or visually dominates over) the logo.
- The Follow button is rendered through the secure-text technique.
- In a screenshot, the secure-text field gets blanked.
- Result: the Follow button vanishes from the captured image, revealing the logo that was “underneath” the button all along.
That also explains the weird feeling from the original observation: the logo is not being dynamically drawn at screenshot time. The logo was already present; the screenshot capture simply omitted the secure-rendered layer that contained the button.
And once you learn to look for this kind of layering trick, it shows up in other places too. Telegram and Signal have used variations of “secure rendering as a capture deterrent” in iOS clients, because iOS doesn’t provide a straightforward, public API that guarantees “block screenshots.”
Why it behaves differently on iOS vs other platforms
The package is named expo-privacy-sensitive, and Expo targets multiple platforms. iOS is where the secure-text behavior can be exploited.
On non-iOS platforms (like Android), there’s no identical secure-text rendering pipeline with the same screenshot blanking behavior. So the package falls back to normal rendering—meaning the secure mask effect doesn’t happen and the logo won’t “unhide” in the same way.
That’s why developers who rely on this pattern typically treat it as iOS-specific.
The mid-switch screenshot problem (timing and snapshots)
The investigation also noted another nuance: the effect sometimes fails when taking a screenshot mid-switching between apps.
That aligns with how iOS captures screenshots under the hood. During app backgrounding/foregrounding and system transitions, iOS may produce a snapshot for performance and gesture continuity. If the secure text field hasn’t made it into the “active” composition pipeline for that snapshot, iOS may screenshot the wrong state.
In other words, the screenshot capture might happen based on:
- what was already committed to the system’s render/snapshot pipeline, vs.
- what would have been blanked if the secure field were live and fully composed at the exact moment.
So the trick isn’t only “what code exists,” but also “what the OS has decided to include at capture time.”
This is genuinely the part that feels like black magic until you imagine the timeline: the secure layer blanking depends on the system knowing, at screenshot composition time, that a secure-rendered subtree exists.
Cleverness vs. fragility (and why the thread got skeptical)
This pattern is clever for two reasons.
First, it doesn’t require Apple-approved screenshot-blocking APIs—because none exist in a public, guaranteed form.
Second, it can be implemented in cross-platform UI code: you mark a region, and iOS does the hiding.
But it’s also fragile.
Apple’s secure text behavior is meant for passwords and sensitive input, not for arbitrary UI masking. Using it as a general screenshot-hiding mechanism relies on internal rendering details that may change. In discussions with platform maintainers, there’s often a warning that this kind of behavior is a side effect rather than a documented feature meant for this use case.
That’s the core tension: developers want a privacy-friendly UI, but the platform doesn’t officially promise that secure rendering will always exclude exactly the same regions from screenshots and screen recordings.
So the behavior can work today, appear broken tomorrow, and vary across iOS versions.
Takeaways for developers building on iOS UI
Even if this specific Bluesky logo watermark is cute, the underlying lesson is serious:
- Secure text entry (
isSecureTextEntry) triggers special iOS rendering paths. - Some apps exploit that behavior to influence what screenshot capture includes.
- The effect depends on timing and rendering composition, not just on “what the UI looks like.”
If a feature must be correct for screenshots (or must prevent them for compliance), relying on an undocumented side-effect is risky.
If the goal is user experience nuance—like revealing an Easter egg watermark only in captured media—then this kind of layered, secure-rendering trick explains how you can get a screenshot to “lie” about the live UI.
And that’s the odd beauty of mobile development: sometimes the platform’s privacy mechanisms become an unexpected drawing tool.
Comments (0)
No comments yet. Be the first to respond!
Leave a Comment
Your comment will be visible after review.