Documentation Python quickstart Blog Free tools hello@quanticdata.ioLog in

Bluesky Proxies: What the API Returns

One unauthenticated Bluesky API request sent through five proxy exit countries on 18 September 2026: the response body is 3,232 bytes from all five, but Germany, Turkey and Brazil also receive a country-specific moderation labeler in the atproto-content-labelers header, while the United States and Japan receive only the global one
One unauthenticated Bluesky API request sent through five proxy exit countries on 18 September 2026: the response body is 3,232 bytes from all five, but Germany, Turkey and Brazil also receive a country-specific moderation labeler in the atproto-content-labelers header, while the United States and Japan receive only the global one

Bluesky is the one large social network that answers a proxied client honestly: its public API needs no account, no token and no browser, and it returned the same bytes to us from five countries on 18 September 2026. What the exit country did change was not the data but the moderation instruction attached to it. Here is every measurement, and the short list of cases where a proxy is actually the right tool.

What bsky.app serves a client that does not run JavaScript

We read one public profile, bsky.app/profile/bsky.app, twice from each of four exit countries on 18 September 2026 between 05:33 and 05:35 UTC: once as a plain HTTP client and once through a real browser.

ExitNo-JS passRendered passVerdict
US200, 47 words, h1 is JavaScript Required200, 1,093 wordsHydrated
BR200, 47 words, identical shell200, 1,107 wordsHydrated
DE200, 47 words, identical shell200, 113 wordsPartial shell
JP200, 47 words, identical shell200, 47 wordsNever hydrated

The no-JS view is the same 47-word shell every time, and its h1 says so out loud. The rendered view is worse than it looks: only two passes out of four produced the post list inside the capture window, and the two that failed returned HTTP 200 with a plausible-looking page. That is the expensive failure mode of rendering a single-page app — you do not get an error, you get a short page you might store as if it were empty.

The server does put something useful in the shell for bots: the title, the profile description, the Open Graph tags and a ProfilePage JSON-LD block are all present without JavaScript, and the canonical URL never goes missing. So a link preview works. A dataset does not. We measured the same split with the SEO Audit API, which fetches both views in one call at $0.0012 per URL.

The public API is the product, and it is unauthenticated

Bluesky runs on the AT Protocol, and its read layer is exposed at public.api.bsky.app. Bluesky's own documentation says these direct endpoints do not support authentication and asks developers to use the cached public host for public web use cases. We confirmed it: no key, no cookie, no session.

RequestStatusOn-wire bytesWhat came back
Profile page HTML, no JS20019,947Nothing readable — an empty shell
Profile page, browser render2002,655,0174,826 words, 58 images, 12.8 s
app.bsky.actor.getProfile2001,054DID, handle, display name, avatar, banner, followers, follows, posts, creation date, pinned post
app.bsky.feed.getAuthorFeed, limit 12003,232One post with text, facets, embeds, plus like, repost, reply, quote and bookmark counts

One kilobyte of JSON answers the question that 2.5 megabytes of rendered page answers badly. The follower count we read from the US exit was 34,942,093 and from Japan, ninety seconds later, 34,942,094 — a live counter, not a regional difference. Responses carry cache-control: public, max-age=30 and are served from a CDN edge in the requesting country.

The practical rule for Bluesky is the opposite of the rule for most platforms: do not render, and do not parse HTML. Point a plain HTTP client at the API, through whatever exit you like. If you want that wrapped — retries, geo pinning, clean output, batching over a URL list — our web scraping API bills $0.0002 per page without rendering and $0.001 with it, and the same calls are available to an agent through the MCP server.

What the exit country really changes

This is the measurement nobody has published. We sent the identical request — app.bsky.feed.getAuthorFeed with limit 1 — through five exit countries within four minutes. The response body was 3,232 bytes from all five. The atproto-content-labelers response header was not.

ExitPayloadLabelers named in the response header
US3,232 Bmoderation.bsky.app
JP3,232 Bmoderation.bsky.app
DE3,232 Bmoderation.bsky.app plus moderation-de.bsky.app
TR3,232 Bmoderation.bsky.app plus moderation-tr.bsky.app
BR3,232 Bmoderation.bsky.app plus moderation-br.bsky.app

Those extra identifiers arrive as raw DIDs. We resolved all four through the same public API: they are the Bluesky Moderation Service and its national counterparts, described in German, Turkish and Portuguese respectively, each created on a different date — Brazil in September 2024, Turkey in March 2025.

So country restrictions on Bluesky are labels, not blocks. The AppView hands your client a list of moderation services appropriate to the IP it sees; honouring them is the client's job, which is exactly why reporting on the Turkish restrictions in 2025 noted that third-party apps did not hide what the official app hid. For a data team this cuts both ways. Rotating your exit will not reveal hidden posts, because nothing was hidden at the API. But pinning an exit is the only way to discover which national labeler applies to a given market, and that is a real brand-safety question: if you publish on Bluesky and want to know whether German or Brazilian readers are being shown a label on your account, you have to ask from inside that country. A country-pinned exit from our residential network answers it for a fraction of a cent.

Which proxy type Bluesky actually needs

The honest answer is the cheapest one. The public API applied no bot challenge, no TLS fingerprint check and no CAPTCHA to any of our fourteen requests, and the payloads are small enough that bandwidth price stops mattering. What you are buying is address diversity against a per-IP request ceiling, not trust.

TypeUse it on Bluesky whenSkip it when
Datacenter, from $0.50/GBReading the public API at volume — this is the default and it is enoughNever, for public reads
Residential, from $0.80/GBYou need a specific country's labeler view, or your datacenter range is being limited as a blockYou only need the data, which is country-independent
Static ISP, from $2.50/IP per month at volumeYou run a long-lived firehose consumer or your own PDS and want a stable, reputable addressShort polling jobs, where rotation is more useful than stability
Mobile, from $2.30/GBWe found no Bluesky read case that justifies itReading public data — you would be paying 4.6 times the datacenter rate for nothing

If you want rotation without managing a pool, the rotating endpoint gives a fresh IP per request from one hostname. A minimal read through a country-pinned exit looks like this:

curl -x http://USER-country-de:PASS@dc.quanticdata.io:7777 \
  "https://public.api.bsky.app/xrpc/app.bsky.actor.getProfile?actor=bsky.app" \
  -D - -o profile.json

Keep the -D -. On Bluesky the headers are half the answer.

Rate limits, and the three errors you will actually see

Bluesky publishes its limits, which is rare enough to be worth quoting precisely. Overall API requests against a PDS or the entryway are limited by IP, at 3,000 per 5 minutes. Write operations are limited per account instead: 5,000 points per hour where a create costs 3 points, an update 2 and a delete 1, which the docs work out to a maximum of 1,666 records created per hour. Account creation is capped at 100 per 5 minutes per IP, and session creation at 30 per 5 minutes per account.

You will read elsewhere that Bluesky's limits attach to identity rather than address. That is true of the write limits and false of the read limits, and the difference decides your architecture: unauthenticated reading is bounded by how many addresses you have, which is the one legitimate reason to put a proxy pool in front of a Bluesky collector at all.

The robots.txt at bsky.app is unusually direct. It greets crawlers, points them at the protocol and its firehose, disallows exactly one path — the compose intent — and states that HTTP 429 is the backoff signal and that "up to a handful concurrent requests should be ok". Read that as your pacing budget: a handful of concurrent connections per address, backing off on 429.

ResponseShapeWhat it means
400JSON: error InvalidRequest, message Profile not found, 56 bytesYour input is wrong, not your IP. A missing handle is a 400 here, not a 404
403HTML from the CDN, no JSON error bodyThe endpoint is not exposed on the public host. We got this on searchPosts: search is not part of the unauthenticated surface
429Documented backoff statusYou crossed a limit. Slow down; changing address does not make the limit go away, it only spreads it
200 with JavaScript Required47-word HTML shellYou fetched the web app instead of the API. Repoint the client

One warning from our own data: none of the successful responses from the public host carried ratelimit- headers, even though the documentation describes header-based backoff for the network's services generally. At the cached public edge you get no advance warning, so treat 429 as the only signal and pace conservatively.

What this costs

All figures at our published rates, using the byte counts measured above.

JobRouteTransferCost
1,000 profile lookupsPublic API1.05 MB$0.0005 at $0.50/GB
1,000 profile lookupsRendered web app2.65 GB$1.24 at $0.50/GB, $2.12 residential
1,000,000 profile lookupsPublic API0.98 GB$0.49 at $0.50/GB
100,000 posts with engagement countsPublic API, author feeds0.30 GB$0.15 at $0.50/GB

Rendering costs 2,519 times the bandwidth of asking the API the same question, and fails two times in four. A gigabyte of datacenter transfer holds roughly 1,018,000 profile responses or 332,000 post records. Every account also gets $2 of free API usage per month, which covers a first pass at a Bluesky dataset without a card. Note one inversion: for responses this small, per-gigabyte proxy billing beats per-page API billing, so the plain proxy route is the cheaper of our two products here. We would rather say that than sell you the wrong one.

There is no Bluesky collector in our catalogue, and given the above there is not much of a case for one — the API is already the clean JSON a collector would hand you. Where collectors earn their keep is on platforms that fight back: Reddit posts at $0.0005 per post, Instagram profiles at $0.006, YouTube search at $0.0008 per video. The contrast with what Instagram returns to a proxied client is the whole argument for the open protocol.

What we will not help you do

The other proxy guides on this keyword sell Bluesky multi-accounting through anti-detect browsers, account warming and registration at scale. We will not write that, for a plain reason: Bluesky's Community Guidelines treat bulk and spammy interaction as a violation, and its own rate-limit documentation names "prolific bots" as the thing the write limits exist to stop. A proxy does not change either fact, and no proxy restores a banned account.

What the open protocol does legitimately support is the rest of the list: public post and profile collection, social listening, creator and audience research, brand monitoring, checking whether a national labeler applies to your own account, and archiving your own organisation's posts. All of it runs on unauthenticated reads, none of it needs an account, and that is why Bluesky is the easiest social platform to work with honestly — the one place where doing it the sanctioned way is also the cheap way.

Two obligations survive the openness. Public does not mean unlicensed: posts remain their authors' content and personal data under the GDPR and similar regimes, so purpose, retention and deletion still apply. And deletion propagates on an open network: if an author removes a post, a dataset that keeps serving it is your problem, not theirs.

Sources & further reading

FAQ

Quick answers on bluesky proxies.

Something else? Ask us →

Do I need a proxy to collect Bluesky data?

Not for small volumes. The public API at public.api.bsky.app is unauthenticated and answered every one of our requests without a challenge. You need a proxy pool when you exceed the documented ceiling of 3,000 API requests per 5 minutes per IP, or when you want to read from inside a specific country to see which national moderation labeler applies there.

Which proxy type is best for Bluesky?

Datacenter, from $0.50/GB. Bluesky applied no bot challenge or fingerprint check to our requests, and the responses are around one kilobyte, so you are buying address diversity rather than trust. Residential at $0.80/GB is worth it only when you need a specific country exit; we found no read case on Bluesky that justifies mobile at $2.30/GB.

Does the exit country change what Bluesky returns?

Not the data. On 18 September 2026 the same request returned exactly 3,232 bytes from the United States, Germany, Turkey, Japan and Brazil. What changed was the atproto-content-labelers header: Germany, Turkey and Brazil each received an additional national moderation labeler, which the client is expected to honour. Country restrictions on Bluesky are applied by the client, not by the API.

Can I scrape bsky.app directly instead of using the API?

You can fetch it, but there is nothing in it. Without JavaScript the profile page is a 47-word shell whose h1 reads JavaScript Required, identical from four countries. Rendering it cost 2,655,017 bytes and still failed to hydrate in two of our four passes, returning HTTP 200 with a short page rather than an error.

What do Bluesky rate limits actually apply to?

Both an address and an account, depending on the operation. Overall API requests against a PDS or the entryway are limited by IP at 3,000 per 5 minutes. Writes are limited per account at 5,000 points per hour, where a create costs 3 points, an update 2 and a delete 1. Crossing a limit returns HTTP 429, which robots.txt names as the backoff signal.

Is searching Bluesky posts available without an account?

No. The app.bsky.feed.searchPosts endpoint on the public host returned 403 with an HTML body from the CDN rather than a JSON error, which is the shape of an endpoint that is not exposed publicly rather than a block on your IP. Author feeds, profiles, threads and follower graphs are available unauthenticated.

Will a proxy help me run multiple Bluesky accounts?

We do not publish that guidance. Bluesky Community Guidelines treat bulk and spammy interaction as a violation, and its rate-limit documentation names prolific bots as the reason the per-account write limits exist. No proxy changes an account-level limit, and none restores a suspended account.

Read Bluesky the cheap way

Datacenter exits from $0.50/GB, country-pinned residential when you need a national view, and $2 of free API usage every month. One key covers proxies, scraping and the MCP server.

Related reading