Get started
Analytics

A stock screener API
with typed, documented filters.

POST /v1/screener filters every active listing in your entitled markets by valuation, dividends, profitability, price, volume, sector and exchange, then sorts the matches. It returns the value of every field you filtered or sorted on, so you can show why each stock matched.

18 fields

13 numeric fields from daily bars and financial metrics, plus sector, industry, country, exchange and asset type.

Up to 20 filters

Conditions are ANDed; values in a set filter are ORed. Missing values never match.

Sorted and paged

Sort on any numeric field, 500 matches per page, cursor pagination.

Refreshed nightly

Screens run on a snapshot rebuilt after the evening end-of-day corrections.

Filter fields

Numeric filters take an operator of gt, gte, lt, lte or eq and a value as a decimal string in the field's unit. Categorical filters take in or not_in and a values array of up to 100 exact categories.

FieldSourceUnit
close, volume, change_percentLatest completed daily barCurrency, shares, percent
market_capitalization, enterprise_valueFinancial metricsCurrency (USD)
pe_ratio, price_to_bookFinancial metricsRatio
dividend_yield, forward_dividend_yield, payout_ratioFinancial metricsRatio (0.03 is 3%)
profit_margin, return_on_equity, revenue_growthFinancial metricsAs defined in metric definitions
sector, industryCompany profileCategory, such as Technology
country, exchange, asset_typeReference dataCategory

Units matter. dividend_yield is a ratio, so 3% is 0.03, while change_percent is already a percentage, so a 5% gain is 5. Each matched value comes back as a measure with its unit, which is the quickest way to check.

How filters combine

  • Every filter must match (logical AND), up to 20 filters per request
  • Numeric values are decimal strings in the field's unit, such as "1000000000" for a $1 billion market capitalization
  • Within an in or not_in filter, any listed value matches (logical OR)
  • A listing with no value for a field never matches a filter on that field, including not_in
  • Requesting a field with no published data returns 422, not an empty result
  • Comparisons use currency_code USD, the only currency the screener supports today

Sorting and pagination

sort takes any numeric field and a direction; the default is market_capitalization descending. Listings without the sort value come after those that have it, so a screen of ETFs or crypto pairs, which have no market capitalization, is best sorted on close or volume. limit runs from 1 to 500. To fetch the next page, repeat the identical body with cursor set to meta.next_cursor.

Liquid technology stocks under 25 times earningsJSON
{
  "filters": [
    { "field": "sector", "operator": "in", "values": ["Technology"] },
    { "field": "pe_ratio", "operator": "lt", "value": "25" },
    { "field": "volume", "operator": "gte", "value": "1000000" }
  ],
  "sort": { "field": "market_capitalization", "direction": "desc" },
  "limit": 50
}

Prices delayed 15 minutes · Illustrative sample data

Reading the response

Each match names the listing in instrument (instrument_id, symbol and name) and its issuer in company_id. values holds every numeric field you filtered or sorted on, each as a measure with value, unit and currency_code. classifications holds the categorical fields you filtered on, such as the matched sector, and is empty when you used none. Use instrument_id to fetch prices, dividends or statements for the matches.

When the data is as of

The screener runs against a daily snapshot of every active listing, built after the evening end-of-day corrections and published at 22:30 New York time. Price fields reflect the latest completed session; metrics reflect the latest eligible observation. observed_at on each match tells you which. The previous snapshot is kept, so as_of can reach back one to two days; an earlier as_of returns 422 point-in-time-unavailable naming the earliest one available. For historical screens, pull financial metrics and daily bars directly.

Common uses

  • Building a watchlist of dividend payers above a size threshold
  • Finding the largest daily movers within one sector
  • Seeding a backtest universe by market capitalization and liquidity
  • Letting an AI assistant answer "find me" questions through the MCP server

Plans

The screener needs the screener.read capability, included on Pro, Commercial and Scale. Each request costs 25 credits, whatever the number of matches, and results are limited to the markets your plan covers.

Large caps yielding at least 3%

RequestcURL
curl -X POST 'https://api.ohlc.io/v1/screener' \
  -H "Authorization: Bearer $OHLC_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"filters":[{"field":"market_capitalization","operator":"gte","value":"100000000000"},{"field":"dividend_yield","operator":"gte","value":"0.03"}],"sort":{"field":"dividend_yield","direction":"desc"},"limit":3}'
Response · Illustrative sampleJSON
{
  "data": [
    {
      "instrument": { "instrument_id": "01M35Z629B6XJDHGX6HFQFFS0R", "symbol": "XNYS:MO", "name": "Altria Group" },
      "company_id": "01M35Z629A6MP5NM7F9ABJGSWE",
      "observed_at": "2026-10-02T20:00:00.000000Z",
      "values": [
        { "field": "dividend_yield", "value": { "value": "0.0616", "unit": "ratio", "currency_code": null } },
        { "field": "market_capitalization", "value": { "value": "114911772672", "unit": "currency", "currency_code": "USD" } }
      ],
      "classifications": []
    }
  ],
  "meta": {
    "timezone": "UTC",
    "as_of": "2026-10-03T15:07:19Z",
    "next_cursor": "Ad1UXuxJ...",
    "coverage": { "status": "partial", "reason": "Coverage is partial for the entitled query scope." }
  }
}

Prices delayed 15 minutes · Illustrative sample data

Questions, answered.

What can I filter on?

Market capitalization, enterprise value, P/E, price to book, dividend yield, forward dividend yield, payout ratio, profit margin, return on equity, revenue growth, close, volume and percent change, plus sector, industry, country, exchange and asset type.

How current is the screener data?

It runs on a snapshot rebuilt each evening and published at 22:30 New York time, so prices reflect the latest completed session. It is not an intraday scanner.

Can I run a screen as of a past date?

Only for the last one to two days, while the previous snapshot is kept. For older dates, combine historical financial metrics with daily bars yourself.

How do I enter a dividend yield of 3%?

As the ratio 0.03. Yields and payout ratios are ratios; change_percent is a percentage.

Which plan includes the stock screener API?

Pro ($149/month) and above, at 25 credits per request. See pricing.

A little JSON.
A lot of possibility.

Explore the API