Contents Lesson 13 of 16

6 min read · practitioner

How do you ask which instruments satisfy a set of conditions?

Every endpoint so far has needed you to already know the symbol. /screener is the one that does not: it takes conditions and returns the instruments that meet them. It is a small query language squeezed into query parameters.

The grammar

  • filters — a JSON array of [field, operation, value] triples, combined with AND. For example [["market_capitalization",">",1000000000],["sector","=","Technology"]].
  • signals — comma-separated pre-computed flags such as 200d_new_hi or bookvalue_pos.
  • sort — a field with a direction suffix: market_capitalization.desc.
  • limit — 1 to 500, default 50. offset — 0 to 999, default 0.

A real call on 2026-07-27, with filters=[["exchange","=","us"],["market_capitalization",">",2000000000000]], sort=market_capitalization.desc and limit=6. The names are stable over a month; the figures and the order are not — run it yourself and expect a different ranking:

AAPL   Apple Inc.              4,948,317,175,808
NVDA   NVIDIA Corporation      4,759,668,391,936
GOOG   Alphabet Inc Class C    3,993,930,039,296
GOOGL  Alphabet Inc Class A    3,993,807,618,048
MSFT   Microsoft Corporation   2,890,404,200,448
AMZN   Amazon.com Inc          2,489,087,688,704

Each row carries code, name, last_day_data_date, adjusted_close, refund_1d, refund_1d_p, refund_5d, refund_5d_p, exchange, currency_symbol, market_capitalization, earnings_share, dividend_yield, sector, industry, avgvol_1d and avgvol_200d. The refund_* fields are this API's word for return; refund_1d_p is the percentage version.

Three things this tiny result already tells you

GOOG and GOOGL are two rows for one company. Share classes are separate rows carrying the same company-wide market cap, each valued at its own class's price — 3,993,930,039,296 and 3,993,807,618,048, apart by 0.003% here because the two class prices were nearly level that day. Divide either figure by that class's price and you get Alphabet's entire share count, not the class's. So a "top six US companies" list built straight from this contains five companies, both rows clear a filter neither class would clear alone, and any sum or weight over the column counts Alphabet twice. Deduplicating by issuer is your job, and the screener gives you no field to do it with.

Every last_day_data_date reads 2026-07-27. The screener answers about the latest day only. There is no "as of 2019-03-01" parameter, so you cannot screen history — and therefore cannot screen a universe containing companies that have since been delisted. That is the survivorship problem from survivorship-and-biases, built into the tool rather than into your code. The only way round it is to run the screen daily and keep every snapshot, starting today.

Drop the exchange filter and the units change underneath you. The same size condition without ["exchange","=","us"] returned CMC Corp on the Vietnamese exchange with market_capitalization 5,403,301,117,952 and currency_symbol ₫, and a Thai listing at 159,858,598,871,040 with ฿. The field is documented as market capitalisation in USD; the values that came back plainly are not all in USD. A numeric filter compares raw numbers, so a global market_capitalization > 1e12 screen selects on currency as much as on size. Converting the rows you got back only removes the false positives; the companies whose nominal figure fell below the threshold in their own currency were never returned, and no client-side arithmetic recovers them. Partition the sweep by exchange or by currency and set the threshold per partition, then convert and merge.

Two filters that match something other than what you meant

sector speaks one vocabulary of two. /fundamentals/{ticker} carries two classifications in General: Sector and Industry, and GICS as GicSector, GicGroup, GicIndustry and GicSubIndustry. Apple is Technology in the first and Information Technology in the second. The screener's sector filter matches the first: on 29 September 2026 ["sector","=","Information Technology"] answered 200 and zero rows, with no error to say the value belongs to the other list.

exchange us is the whole .US code, over-the-counter lines included. A dividend screen on it, largest first, opened with TCTZF, IDCBF and IDCBY, OTC listings of Chinese companies, and every row's exchange column read US whatever venue the line trades on. Filtering on NYSE or NASDAQ drops the OTC lines but not the preferred shares, JPM-PC and friends, because a row carries no instrument type at all. General.Type from /fundamentals is the second call that tells a common stock from a preferred.

The pagination ceiling

offset caps at 999 and limit at 500, so the furthest row you can reach is number 1,499. A condition matching 40,000 instruments simply cannot be enumerated through this endpoint. Narrow with filters, or partition the sweep by exchange or sector and page within each partition.

The screener answers "which rows satisfy these conditions". It says nothing about whether the conditions are worth satisfying, and this course makes no suggestion about which conditions anyone should use.

Try it now

  1. Here is the size filter from above with and without the exchange constraint, the top three rows of each. Compare currency_symbol across the two result sets, and say which of the unconstrained rows would survive conversion to dollars. The units problem takes about thirty seconds to reproduce.
Live API response: mda12 screener us over 2t
Live API response: mda12 screener any over 2t
  1. Save today's screen output to a dated file. Do it again tomorrow. You have started the only historical screening universe you will ever be able to trust.

  2. Count how many rows your intended screen matches, then work out whether 1,499 is enough. The Terminal's screener runs the same kind of filter with no key of your own: open it with a size condition filled in and change the conditions to yours. If 1,499 is not enough, design the partitioning now rather than after the job silently truncates.

  3. Here is the same dividend screen twice, on exchange us and on exchange NYSE. Mark each code as an ordinary share, an over-the-counter line or a preferred, say which marks you could make from the screener row alone, and name the call that settles the rest.

Live API response: mda4 screener us otc lines
Live API response: mda4 screener nyse preferreds