NEW: Live arbitrage across 10+ prediction markets.Arbitrage →
← Index
APIOct 5, 2026

Polymarket Search API (2026): Find Markets and Events by Keyword

Polymarket Search API (2026): Find Markets and Events by Keyword

The Short Answer

Polymarket's keyword search is Gamma's public GET https://gamma-api.polymarket.com/public-search?q= endpoint. One call returns matching events with their markets nested inside, plus tags and trader profiles when you ask for them. Add events_status=active for open events, events_tag to filter by tag slug, sort to rank by volume or dates, and limit_per_type with page to page through results. No API key is needed, the limit is 350 requests per 10 seconds as of October 2026, and the unified SDK wraps the endpoint as search(). In our checks on 3 October 2026, "bitcoin" matched 137,559 results in total and 854 with events_status=active.

Key Takeaways

  • q is required, and an empty one returns a 422, so trim user input and skip blank queries.
  • events_status=active keeps open events, but check each event's closed flag too, because some closed events still matched in our checks.
  • events_tag takes tag slugs and narrows the results with each repeat, while exclude_tag_id takes numeric tag ids.
  • Events arrive with their markets and condition ids, but outcomes, outcomePrices and clobTokenIds are JSON strings you have to parse.
  • Responses were cached for up to five minutes, so treat prices in search results as a snapshot.

How do you search Polymarket markets with the API?

Send a keyword to /public-search. This returns ten active events matching "bitcoin":

curl -s "https://gamma-api.polymarket.com/public-search?q=bitcoin&events_status=active&limit_per_type=10"

The response is an events array plus a pagination object. Each event is a full Gamma event, so it carries its markets, volume, dates and comment count. Fields are trimmed here:

{
  "events": [
    {
      "id": "1112205",
      "slug": "what-price-will-bitcoin-hit-in-october-2026",
      "title": "What price will Bitcoin hit in October?",
      "active": true,
      "closed": false,
      "volume24hr": 934720.119706,
      "markets": [
        {
          "question": "Will Bitcoin reach $150,000 in October?",
          "conditionId": "0x8717c39520cadcb8ad6f88af148c30acf7d044c92a9cf48416b9b9a5ed65d6d8",
          "outcomes": "[\"Yes\", \"No\"]",
          "outcomePrices": "[\"0.0055\", \"0.9945\"]",
          "closed": false
        }
      ]
    }
  ],
  "pagination": { "hasMore": true, "totalResults": 854 }
}

Each market's conditionId is the id the Data API and CLOB expect, and clobTokenIds holds the outcome token ids for order books. tags and profiles keys only appear when you set search_tags=true or search_profiles=true. Responses are large, at about 400 KB for five active "bitcoin" events with their markets.

What parameters does Polymarket's search endpoint take?

Gamma's OpenAPI spec lists the parameters without descriptions, so the behavior below is what we observed on 3 October 2026, with sort values from the official SDK.

ParameterWhat it does
qRequired search text. Empty or missing returns a 422
events_statusactive keeps open events and resolved keeps closed ones
events_tagA tag slug such as crypto. Repeat it to require several tags
exclude_tag_idA numeric tag id to leave out, such as 21 for Crypto
sort, ascendingvolume, volume_24hr, liquidity, competitive, start_date, end_date or closed_time. Descending unless ascending=true
limit_per_type, pageResults per type (default 5, capped at 50 in our checks) and the page number
search_tags, search_profilesAlso return matching tags and trader profiles. Off by default
recurrencedaily, weekly or monthly, for recurring events
keep_closed_marketsAn hour window that keeps recently closed markets in an active search
optimizedReturns a slimmer event and market shape

limit_per_type applies to each result type separately, so limit_per_type=8 with tags and profiles switched on returned eight events, eight profiles and every matching tag. optimized=true cut a five-event response from about 258 KB to 40 KB, but its markets carry no conditionId or clobTokenIds, and it moves hasMore to the top level.

How do you filter search results by tag and status?

Tags use two identifiers. events_tag wants the slug, and exclude_tag_id wants the numeric id. GET /tags/slug/crypto returns both, an id of "21" and a slug of crypto, and so does a search with search_tags=true.

Repeating events_tag narrows the results rather than widening them. In our checks, an active search for "trump" matched 372 results, 325 with events_tag=politics, 9 with events_tag=crypto, and 8 with both tags as separate parameters. Joining them with a comma, as events_tag=crypto,politics, matched nothing. Going the other way, exclude_tag_id=21 left six active "bitcoin" events outside the Crypto tag.

Status needs a second check. events_status=active cut "bitcoin" from 137,559 matches to 854, yet when we sorted that active search by end_date or liquidity, events with closed: true still came back. Filter on each event's closed flag, and on each market's, before you display or trade anything. To keep markets that closed recently, such as yesterday's daily markets, add keep_closed_markets=24 for a 24-hour window.

recurrence isolates repeating series. Among active "bitcoin" events it matched 9 daily, 26 weekly and 2 monthly events.

How do you build a market search in JavaScript?

This turns a keyword into a flat list of open markets with their Yes price and condition id. It runs on Node 18 or newer with no dependencies:

const GAMMA = 'https://gamma-api.polymarket.com';

async function searchMarkets(q, { tag, limit = 10, page = 1 } = {}) {
  const url = new URL('/public-search', GAMMA);
  url.searchParams.set('q', q);
  url.searchParams.set('events_status', 'active');
  url.searchParams.set('sort', 'volume_24hr');
  url.searchParams.set('limit_per_type', String(limit));
  url.searchParams.set('page', String(page));
  if (tag) url.searchParams.append('events_tag', tag);

  const res = await fetch(url);
  if (!res.ok) throw new Error(`public-search returned ${res.status}`);
  const { events = [], pagination } = await res.json();

  const markets = events
    .filter((event) => !event.closed)
    .flatMap((event) =>
      (event.markets ?? [])
        .filter((market) => !market.closed)
        .map((market) => ({
          event: event.title,
          question: market.question,
          yes: Number(JSON.parse(market.outcomePrices ?? '[]')[0]),
          conditionId: market.conditionId,
        })),
    );

  return { markets, hasMore: pagination?.hasMore ?? false };
}

const { markets, hasMore } = await searchMarkets('bitcoin', { tag: 'crypto' });
console.table(markets.slice(0, 10));
console.log({ hasMore });

outcomePrices is a JSON-encoded string, so it needs JSON.parse before use. Every search response we checked carried Cache-Control: public, max-age=300, and one arrived 217 seconds old, so read live prices from the CLOB before acting on a result. Page with page while hasMore is true.

For browsing a tag without a keyword, Gamma's listing endpoints are the better tool, covered in our Polymarket Gamma API guide. Search is for text.

How do you search with Polymarket's SDK?

The unified TypeScript SDK exposes the same filters in camel case, with the sort values as an enum:

import { createPublicClient, SearchSort } from '@polymarket/client';

const client = createPublicClient();

const pages = client.search({
  q: 'bitcoin',
  eventsStatus: 'active',
  eventsTag: ['crypto'],
  sort: SearchSort.Volume24Hr,
  ascending: false,
  pageSize: 10,
});

const { items } = await pages.firstPage();
for (const event of items.events) {
  console.log(event.id, event.slug, event.title);
}

items holds events, tags and profiles. Events come back as the SDK's normalized type, with markets that carry conditionId and positionIds, so nothing needs parsing. The SDK trims the query and rejects whitespace-only input, and pages.from(page.nextCursor) continues to the next page. Python's equivalent is client.search(q=..., page_size=...).

Profile search is useful on its own. With search_profiles=true, each profile carries name, pseudonym and proxyWallet, and that wallet is what the Data API accepts for positions and activity, as shown in our Polymarket Data API guide.

How do you search every prediction market at once?

Gamma searches Polymarket. The same event often trades on Kalshi, Limitless and other venues, each with its own search syntax and response shape. The Predictefy API searches 15+ venues through its router in one request, and returns every match in one normalized market shape:

import Predictefy from '@predictefy/sdk';

const client = new Predictefy({ apiKey: process.env.PREDICTEFY_API_KEY });

const markets = await client.router.fetchMarkets({
  query: 'bitcoin',
  status: 'active',
  sort: 'volume',
  limit: 50,
});

for (const market of markets) {
  console.log(market.sourceExchange, market.title, market.volume24h, market.url);
}

sourceExchange names the venue that served each row, and each search costs 1 credit. Swap router for polymarket to scope the same call to one venue, or add category: 'politics' to filter on Predictefy's canonical categories, which read the same across venues.

Frequently Asked Questions

Does Polymarket have a search API?

Yes. GET /public-search on gamma-api.polymarket.com takes a keyword in q and returns matching events with their markets nested inside, plus tags and trader profiles when requested. It needs no API key and allows 350 requests per 10 seconds.

How do I search only active Polymarket markets?

Add events_status=active, then check each event's and market's closed flag, because some closed events still matched in our checks. To keep markets that closed in the last few hours, add keep_closed_markets with a window in hours.

How do I filter Polymarket search results by category?

Pass a tag slug such as politics or crypto in events_tag. Repeat the parameter to require several tags, since a comma-joined value matched nothing in our checks. To leave a tag out, pass its numeric id in exclude_tag_id.

How many results does Polymarket search return per request?

Five per result type by default. limit_per_type raises that, and it was capped at 50 events per page in our checks. Use page for more, and stop when pagination.hasMore is false.

Can I search for Polymarket traders by name?

Yes. Set search_profiles=true and the response adds profiles with name, pseudonym and proxyWallet. The proxy wallet is the address the Data API accepts for a trader's positions, trades and activity.

Why does Polymarket's search return a 422 error?

The q parameter was missing or empty, and Gamma answers with a validation error saying the query is empty. Trim the user's input and skip the request when nothing is left.