Bluesky Search Operators: Every One Tested (2026)
Bluesky's advanced search is eleven pieces of syntax: the operators from:, to:, mentions:, since:, until:, domain: and lang:, plus quoted phrases, #hashtags, a pasted URL, and a leading - to exclude a word. There is nothing else — no engagement filter, no media filter, no boolean logic. And anything you type that looks like an operator but isn't one gets searched for as literal text, so a Twitter-style query doesn't error, it just quietly comes back empty. That last part is why Bluesky search feels broken far more often than it is.
Most of the pages ranking for this query list the same operators, and they're all traceable to the same source: Bluesky's own "Tips and Tricks for Bluesky Search" post from May 31, 2024. They're not wrong to. But a list copied out of a two-year-old blog post can't tell you whether the operators still do what they said, and at least one ranking guide has quietly added operators that don't exist. So I ran the whole set against Bluesky's live AppView on August 31, 2026 and checked the records that came back, rather than just noting that something did.
Four of them don't behave the way the guides say: to: is a synonym, url: isn't a prefix at all, OR isn't boolean, and until: currently can't be reached from the public API.
What Search Operators Does Bluesky Support?
These eleven, and only these eleven. Every row below is a real query run unauthenticated against app.bsky.feed.searchPosts on api.bsky.app on August 31, 2026, asking for 50 results, with every returned record then checked against what the operator claims to do:
| Query I ran | What it's for | What came back |
|---|---|---|
from:jay.bsky.team |
Posts by one account | 50 posts, 50/50 from that account |
mentions:jay.bsky.team |
Posts mentioning an account | 47 posts, 47/47 tagging them |
to:jay.bsky.team |
Documented as "posts that mention" | The same 47, in the same order |
cats since:2026-08-30 |
Posts on or after a date | 49 posts, 49/49 on or after |
cats until:2026-08-01 |
Posts before a date | HTTP 403 from api.bsky.app |
domain:github.com |
Posts linking a domain | 50 posts, 50/50 linking it |
lang:ja |
Posts in one language | 50 posts, 50/50 declared ja |
"the quick brown fox" |
Phrase match | 49 posts, 33 in text + 16 in alt text or link cards |
#caturday |
Tagged posts | 49 posts, 49/49 carrying the tag |
cats -dogs |
Exclude a word | 49 posts, 0 mentioning dogs |
https://github.com/… (pasted) |
Posts sharing a link | 20 posts, 20/20 linking it |
Reproduce any row with one line — there's no key, no login, no app password:
curl -s -G 'https://api.bsky.app/xrpc/app.bsky.feed.searchPosts' \
--data-urlencode 'q=from:jay.bsky.team' --data-urlencode 'limit=50'
(Those totals are page sizes against a corpus that moves, not a census — 47 and 49 mean "a full page, minus what moderation filtered out." The ratios are the finding; the totals are just what was there on Monday afternoon.)
Combine operators with a space and they AND together: from:jay.bsky.team since:2026-01-01, lang:ja bluesky, cats -dogs.
Three things the lists never mention. The @ is optional — from:@jay.bsky.team returned the same 50 posts in the same order as from:jay.bsky.team. The case is not — from:JAY.BSKY.TEAM returned zero, and since phone keyboards capitalise the first letter of what you type, that failure is going to find you eventually. And from:me needs a session: Bluesky documents it for logged-in users, and called without credentials it doesn't return an empty list, it fails with HTTP 400 InvalidRequest.
Quotes do more work than people expect. "the quick brown fox" returned 49 posts; the same four words unquoted returned 50 posts of which only 8 contained the phrase. And I could account for all 49 quoted matches: 33 had it in the post text, 14 in an image's alt text, and 2 in the title or description of a link card. Bluesky's post promises that alt text is searchable; that's what the promise looks like from outside.
One caveat on lang: that nobody states. All 50 results for lang:ja had langs: ["ja"] on the record — which is the language the posting app declared, not a language the search engine detected. A post written in Japanese from a client that never set the field won't show up, and neither will your English post if your client is set to something else.
The pasted-URL row hides a trap of its own. Pasting https://github.com/alam00000/bentopdf into search returned 20 posts sharing that link, exactly as documented. Writing it as url:https://github.com/alam00000/bentopdf returned 0. url is a genuine filter, but it's a query parameter on the API endpoint — right next to author, tag and sort in the lexicon — and not a prefix you can type into the box.
Why Does My Bluesky Search Return Nothing?
Because Bluesky doesn't reject an unsupported operator — it searches for it as a word. None of the pages currently ranking for this query say so, and it's the single most useful thing to know about Bluesky search.
The lexicon is candid about why. It describes its own q parameter like this:
Search query string; syntax, phrase, boolean, and faceting is unspecified, but Lucene query syntax is recommended.
Unspecified means there's no grammar to violate. Type something that isn't a known filter and it falls straight through to full-text matching. Plain cat returned 50 posts. Then:
| Query | Posts returned |
|---|---|
cat (control) |
50 |
cat has:image |
0 |
cat has:link |
0 |
cat has:images |
0 |
cat filter:images |
0 |
cat filter:links |
0 |
cat min_faves:100 |
0 |
cat is:reply |
0 |
cat list:12345 |
0 |
cat near:london |
0 |
cat zzzop:foo (invented) |
0 |
Every real operator in that table scored exactly what zzzop:foo scored, and zzzop:foo is one I made up on the spot. That's the tell: Bluesky isn't refusing them, it's looking for them, and approximately nobody writes the literal string has:image into a Bluesky post.
Which matters, because SocialMention's Bluesky search guide — currently ranking for this query — lists has:link ("Posts that contain a URL") and has:image ("Posts that contain an image") in its operator reference, and offers "product launch" has:image lang:en as a worked example. Run that pattern and you get an empty page. It isn't that the filter is unreliable; there is no media filter on Bluesky at all.
Here's the translation table I wish I'd had when I moved over:
| Twitter habit | Bluesky equivalent |
|---|---|
filter:links, has:link |
Nothing generic — use domain: for a specific site |
filter:images, has:image |
Nothing. There is no media filter |
min_faves:, min_retweets: |
Nothing. No engagement filter of any kind |
is:reply |
Nothing — and to: won't do it either (below) |
-word |
-word, one of the few that carries over intact |
url:example.com/page |
Paste the bare URL instead |
OR |
Run two searches |
Does Boolean OR Work on Bluesky Search?
No, and it fails in the way that's hardest to notice — by returning plausible results. SocialMention's guide puts "Boolean OR" in a comparison table with OR in both the Bluesky column and the X column. Bluesky's own 2024 post never mentions boolean anything, and the lexicon explicitly calls boolean handling "unspecified."
Here's what the three keywords actually do:
| Query | Posts | Contain the keyword as a word | Contain both cat and dog |
|---|---|---|---|
cat OR dog |
49 | 42 contain "or" | 42 |
cat AND dog |
49 | 37 contain "and" | 36 |
cat NOT dog |
47 | 36 contain "not" | 32 still mention dogs |
Read the last column. If OR were a union you'd expect a pile of cat-only and dog-only posts; instead 42 of 49 results contain both terms, and 42 also happen to contain the English word "or". NOT is worse than useless — 32 of its 47 results talk about dogs, the exact thing you asked it to remove. The one that does work is the plain minus: cats -dogs returned 49 posts and not one of them mentioned a dog.
So: to exclude, use -. To union, run two searches and merge them yourself. Typing OR just adds a common English word to your query and narrows it.
Why Does until: Return a 403 on Bluesky's Public API?
Because something in front of the AppView refuses the request before it's answered — and it's refusing the letters, not the operator. This was the oddest result of the day and I went at it several ways before believing it.
On api.bsky.app, the host that answers post search without a login, every query containing the string until came back HTTP 403 Forbidden with an HTML body reading "Request forbidden by administrative rules." That isn't an atproto error shape at all — a real search failure returns JSON. Meanwhile since: was fine throughout:
| Query | Status |
|---|---|
cats (control) |
200, 50 results |
cats since:2026-08-30 |
200, 49 results |
cats until:2026-08-01 |
403 |
cats until:2026-08-01T00:00:00Z |
403 |
until:2024-01-01 |
403 |
untilx:2026-08-01 cats |
403 |
untilled (an ordinary English word) |
403 |
wait until tomorrow |
403 |
The untilled row is the giveaway. This is a substring rule, not an operator rule — and it catches Bluesky's own documented date filter along with any post you wanted to find about untilled soil or waiting until Friday. It isn't about the client, either: a Chrome user-agent gets the identical 403, and so does a control cats request sent twenty-five seconds later, which comes back 200.
That signature is a known shape rather than a fluke of my afternoon. atproto issue #3583, "Adding cursor to searchPosts Request Returns 403 Forbidden," opened February 25, 2025, reports the same endpoint returning the same HTML "Request forbidden by administrative rules" for a different innocuous parameter. Something at the edge in front of searchPosts is pattern-matching request strings, and it has false positives.
Signed in, in the app, until: should still work as documented — I have no way to test the app's authenticated path from here, so treat that as inference rather than measurement. Building against the public API, pass the structured until query parameter on searchPosts instead of putting it inside q.
Two more date details while you're in that lexicon, both of which change results and neither of which appears in any guide I found. since is inclusive and until is not, so since:2026-08-01 until:2026-08-31 quietly ends at the close of August 30. And both are "expected to use sortAt timestamp, which may not match createdAt" — meaning the filter runs on when Bluesky indexed the post, so a backdated or slowly-relayed post can land outside the window you asked for.
Does to: Actually Find Replies on Bluesky?
No. to: is a synonym for mentions:, and this one I can show rather than assert. Bluesky's 2024 post lists to:jay.bsky.team and mentions:jay.bsky.team side by side as ways to "show posts that mention the user" — but the name invites everyone to read it as Twitter's to:, meaning replies addressed to someone.
I ran both and compared the returned post URIs:
to:jay.bsky.team→ 47 postsmentions:jay.bsky.team→ 47 posts- The same 47 URIs, in the same order. The two responses are identical down to the cursor.
Of those 47, only 21 were replies at all; the other 26 were top-level posts that happened to tag the account. So to: doesn't narrow to replies, doesn't narrow to anything, and exists purely as an alias — which is exactly what mary-ext's syntax notes call it ("currently an alias for mentions"). Nice to have the receipt.
One consequence worth knowing: the lexicon says mentions matches "rich-text facet mentions" only. All 47 results carried a real tag pointing at his DID. If someone types your handle as plain text without tagging you, mentions: will never find it — for that, search your handle in quotes, "@yourhandle.bsky.social", which matches characters instead of tags.
What Can't Bluesky Search Operators Do?
They can find people, but they can't do anything with them. The finding half is genuinely strong: pair lang: with a niche term and you have the fastest route I know into a language community. domain: on a publication you respect turns up the people who share it, which beats any "top accounts to follow" roundup. Hashtags hold up here too, because Bluesky's are real facets rather than decoration. Stack a date range on from: and you can narrow one person's history to one week.
Then the query returns 300 relevant accounts and you're looking at 300 profile pages, one at a time. That's the point where most people quietly give up on finding people to follow, and it's the gap Agent Sky fills — I'd rather name the conflict than bury it, since I sell the thing. $9 a month, free to start. You describe the niche in words instead of query syntax; it follows accounts inside Bluesky's published rate limits rather than in a burst, and it confirms a follow-back really happened before it unfollows anyone. When I last re-ran our own numbers on August 26, 2026, the median Agent Sky account had gained +326 followers over the trailing 30 days (median across the 20 accounts with a full 30-day history — the growth study has the method and the spread).
If you'd rather do it by hand, do it by hand. The eleven pieces of syntax above are the whole toolkit, and a custom feed will keep a good query running for you afterwards — which is also the workaround if you're stuck reading logged out, where post search is refused outright.
Bluesky search never tells you that you're wrong. It hands you an empty page and lets you conclude the network is empty. Eleven pieces of syntax, and the most important thing about them is knowing there is no twelfth.
Quick FAQ
Does Bluesky have advanced search?
Yes, but it is a short list: seven prefixed operators — from:, to:, mentions:, since:, until:, domain: and lang: — plus quoted phrases, #hashtags, a pasted URL, and a leading minus to exclude a word. Bluesky's own search post of May 31, 2024 documents everything there except the minus, which works but isn't mentioned in that post or in the lexicon. There is no engagement filter, no media filter and no boolean logic, so the Twitter habits of min_faves:, filter:images, has:image and OR have no Bluesky equivalent.
How do I search Bluesky posts by user?
Type from:handle — for example from:jay.bsky.team. Run against Bluesky's AppView on August 31, 2026, that returned a page of 50 posts, all 50 from that one account. The leading @ is optional (from:@jay.bsky.team returned the identical 50 in the identical order), but the case is not: from:JAY.BSKY.TEAM returned zero. Handles have to be lowercase, which is a real trap on a phone, where the keyboard capitalises the first letter for you. Bluesky also documents from:me, which needs a session — called without one it fails with HTTP 400 InvalidRequest.
How do I search Bluesky posts by date?
Use since:YYYY-MM-DD and until:YYYY-MM-DD, alone or alongside search words. On August 31, 2026 the query cats since:2026-08-30 returned 49 posts and all 49 were created on or after that date. Three catches: since: is inclusive and until: is not, so since:2026-08-01 until:2026-08-31 stops at the end of August 30; the lexicon says both are expected to filter on the post's sortAt indexing timestamp, "which may not match createdAt"; and on the public API host every query containing the string until came back HTTP 403 the whole time I was testing.
Why is my Bluesky search not working?
Usually because Bluesky is reading your operator as an ordinary search word. Unsupported syntax is not rejected — it is matched literally, so cat has:image hunts for posts containing the string "has:image", finds none, and returns an empty page where plain cat returns a full one. It scored exactly the same as an operator I invented. The other two common causes are capitalisation in from:, and searching while logged out, where post search is refused outright on Bluesky's cached public host.