Bluesky has implemented age verification measures in response to regional laws that restrict access, prompting users to verify their age through Epic Games' Kids Web Services before they can access adult content.
This sucks, but thankfully there are ways to work around it.
Before diving in: I encourage you to read this entire document, including the Background section explaining why these workarounds work, and What you can do next for ways to address the root cause.
This was obvious, but using a VPN to connect from outside your location will bypass the age assurance requirements entirely.
If you don't already have one, a VPN routes your connection through servers in other countries and prevents your ISP from tracking and selling your browsing data, though you're essentially trading trust from your ISP to your VPN provider instead.
My personal recommendations are Mullvad, IVPN or ProtonVPN.
Don't fall for VPN services that heavily focus on marketing, especially if they market features like "military-grade encryption" or make exaggerated privacy claims.
You don't have to use the official Bluesky app to access the platform.
Note that these alternatives work only as long as their developers don't implement similar age assurance measures or block users outright.
- my own thing (no support is provided)
- mu
- Witchsky
You can add the following filter rules to your adblocker.
||ip.bsky.app/geolocation$replace=/.*/{"countryCode":"US","regionCode":"DE"}/
/xrpc/app.bsky.ageassurance.getConfig$replace=/.*/{"regions":[]}/
/xrpc/app.bsky.ageassurance.getState$replace=/.*/{"state":{"lastInitiatedAt":"2025-07-14T14:22:43.912Z","status":"assured","access":"full"},"metadata":{"accountCreatedAt":"2022-11-17T00:35:16.391Z"}}/
! for Chrome MV2/Helium users
bsky.app,main.bsky.dev##+js(trusted-replace-fetch-response, '/.*/', '{"countryCode":"US","regionCode":"DE"}', 'ip.bsky.app/geolocation')
bsky.app,main.bsky.dev##+js(trusted-replace-fetch-response, '/.*/', '{"regions":[]}', '/xrpc/app.bsky.ageassurance.getConfig')
bsky.app,main.bsky.dev##+js(trusted-replace-fetch-response, '/.*/', '{"state":{"lastInitiatedAt":"2025-07-14T14:22:43.912Z","status":"assured","access":"full"},"metadata":{"accountCreatedAt":"2022-11-17T00:35:16.391Z"}}', '/xrpc/app.bsky.ageassurance.getState')
- Open uBlock Origin dashboard › My filters
- Enable Enable my custom filters
- Enable Allow custom filters requiring trust
- Add the rules provided above
- Open Settings › Shields › Content filtering
- Enable Developer mode
- Add the rules provided above to Create custom filters
- Open Ghostery extension window › Ad-Blocking › Custom Filters
- Make sure it's enabled
- Add the rules provided above
- Open Adguard Settings › User Rules
- Make sure it's enabled
- Add the rules provided above
Note: Custom filter rules is a paid feature on the Android version.
Based on testing, this seems to produce wonky results. The setup process is also more complex. But if it works, it allows you to use Bluesky's Android app as usual.
- Create a text file containing the filter rules provided above and save it to somewhere accessible
- Open Adguard and navigate to Settings › Filtering › Filters › Custom Filters › Add custom filter
- Tap Browse and locate the text file you created
- Select the file to add it as a custom filter list
Chrome's Manifest v3 changes broke all adblockers including uBlock Origin by replacing the webRequest API that they rely on with the less powerful declarativeNetRequest API instead. uBlock Origin Lite was created specifically to work with DNR, and thankfully it's still very usable for our purposes.
- Install uBlock Origin Lite
- Open uBlock Origin Lite dashboard
- Enable Developer mode
- Head to Develop › View: Custom DNR rules
- Insert the following rules:
---
priority: 1
action:
type: redirect
redirect:
url: https://gist.githubusercontent.com/mary-ext/6e27b24a83838202908808ad528b3318/raw/geolocation-response.json
condition:
requestDomains:
- ip.bsky.app
initiatorDomains:
- bsky.app
- main.bsky.dev
urlFilter: /geolocation
resourceTypes:
- xmlhttprequest
---
priority: 1
action:
type: redirect
redirect:
url: https://gist.githubusercontent.com/mary-ext/6e27b24a83838202908808ad528b3318/raw/getConfig-response.json
condition:
initiatorDomains:
- bsky.app
- main.bsky.dev
urlFilter: /xrpc/app.bsky.ageassurance.getConfig
resourceTypes:
- xmlhttprequest
---
priority: 1
action:
type: redirect
redirect:
url: https://gist.githubusercontent.com/mary-ext/6e27b24a83838202908808ad528b3318/raw/getState-response.json
condition:
initiatorDomains:
- bsky.app
- main.bsky.dev
urlFilter: /xrpc/app.bsky.ageassurance.getState
resourceTypes:
- xmlhttprequest
---You can use userscripts, or scriptlets in Brave.
-
Install a userscript manager
- Chrome: Violentmonkey
- Firefox: Violentmonkey
- Edge: Violentmonkey
- Safari: Userscripts
-
Install this userscript
Open Settings › Shields › Content filtering (or go to about:adblock)
Enable Developer mode, and add the following scriptlet, saving it as user-bsky-age-assurance.js.
const _fetch = globalThis.fetch;
globalThis.fetch = async function (req, init) {
if (req instanceof Request) {
const url = new URL(req.url);
switch (url.pathname) {
case '/xrpc/app.bsky.ageassurance.getConfig': {
return Response.json({
regions: [],
});
}
case '/xrpc/app.bsky.ageassurance.getState': {
return Response.json({
state: {
lastInitiatedAt: '2025-07-14T14:22:43.912Z',
status: 'assured',
access: 'full',
},
metadata: {
accountCreatedAt: '2022-11-17T00:35:16.391Z',
},
});
}
}
} else if (req === 'https://ip.bsky.app/geolocation') {
return Response.json({
countryCode: 'US',
regionCode: 'DE',
});
}
return _fetch.call(this, req, init);
};Then reference the scriptlet in a custom filter.
bsky.app,main.bsky.dev##+js(user-bsky-age-assurance.js)
If your account is hosted on a PDS you own or control, you can add these rules to your Nginx or Caddy configuration.
server {
server_name pds.example.com;
location /xrpc/app.bsky.ageassurance.getState {
default_type application/json;
add_header access-control-allow-headers "authorization,dpop,atproto-accept-labelers,atproto-proxy" always;
add_header access-control-allow-origin "*" always;
return 200 '{"state":{"lastInitiatedAt":"2025-07-14T14:22:43.912Z","status":"assured","access":"full"},"metadata":{"accountCreatedAt":"2022-11-17T00:35:16.391Z"}}';
}
}
pds.example.com {
handle /xrpc/app.bsky.ageassurance.getState {
header content-type "application/json"
header access-control-allow-headers "authorization,dpop,atproto-accept-labelers,atproto-proxy"
header access-control-allow-origin "*"
respond `{"state":{"lastInitiatedAt":"2025-07-14T14:22:43.912Z","status":"assured","access":"full"},"metadata":{"accountCreatedAt":"2022-11-17T00:35:16.391Z"}}` 200
}
}
Bluesky's implementation of age-based content restrictions is entirely client-side, this is an intentional design decision. The API (called the "AppView") doesn't impose content restrictions directly and isn't aware of your location as requests to it are proxied through the hosting server that your account resides in (called the "PDS.")
bsky.app (or the "client") determines your location and restriction status through a series of API calls:
-
https://ip.bsky.app/geolocationreturns your location:countryCode: your country based on IP addressregionCode: your state/region code
-
<pds host>/xrpc/app.bsky.ageassurance.getConfigreturns the restriction configuration:regions: list of regions with age assurance requirements
-
<pds host>/xrpc/app.bsky.ageassurance.getStatereturns your verification status:state.status: your account's verification statusstate.lastInitiatedAt: when you last started identity verificationstate.access: your access level (full,limited, etc.)metadata.accountCreatedAt: when your account was created
These workarounds exploit the client-side nature of these checks.
Worth noting that decentralized social networks aren't above the law. All platforms, including Mastodon and other federated networks, must comply with local regulations like the Online Safety Act, and a fully decentralized network may need individual server operators to handle compliance.
It remains unclear whether regulators would consider Bluesky's client-side implementation sufficient for legal compliance. However, Bluesky Social PBC could reasonably argue the restrictions are effectively enforced for users on their PDS using unmodified clients, and that's as far as they can guarantee in a decentralized network like Bluesky.
I am not a lawyer however.
Yelling at Bluesky might feel good, but this issue only exists because your lawmakers passed it, and they're the ones who can repeal it. Consider taking action to address the root cause:
The ask is the same wherever you are: tell your lawmakers how age-verification mandates harm privacy, free speech, and digital rights. Find your representatives and the relevant law below.
| Region | Relevant law | Find your representatives |
|---|---|---|
| Australia | Online Safety Amendment ("Social Media Minimum Age") Act 2024 | Australian Parliament |
| UK | Online Safety Act | UK Parliament |
| Brazil | Lei nº 15.211/2025 (the "ECA Digital") | Câmara dos Deputados · Senado Federal |
| Mississippi | HB 1126 | Mississippi Legislature |
| Ohio | HB 96 | Ohio Legislature |
| South Dakota | HB 1053 | South Dakota Legislature |
| Tennessee | HB 1891 | Tennessee General Assembly |
| Texas | SB 2420 (the "App Store Accountability Act") | Texas Legislature |
| Virginia | SB 854 | Virginia General Assembly |
| Wyoming | HB 43 | Wyoming Legislature |
Consider supporting or getting involved with organizations that advocate for digital rights and privacy:
International:
- Electronic Frontier Foundation (EFF) - Defends civil liberties in the digital world
- Internet Freedom Foundation - Works to ensure that technology respects fundamental rights
Australia-specific:
- Digital Freedom Project - Challenging Australia's social media age ban in the High Court
- Electronic Frontiers Australia - Campaigns for digital freedoms and civil liberties online
UK-specific:
- Open Rights Group - Campaigns for digital rights and freedoms in the UK
- Big Brother Watch - Fights for privacy, free speech and civil liberties
US-specific:
- American Civil Liberties Union (ACLU) - Defends constitutional rights including digital privacy
- Fight for the Future - Campaigns for digital rights and internet freedom
they're just dates i picked at the time