---
name: scanr-stock-scanner
description: Screen the U.S. stock market with the scanr.ai API or MCP server. Use when asked to find, screen, filter or scan for stocks by price, volume, technical indicators (RSI, moving averages, MACD, crosses), relative strength, fundamentals, candlestick or chart patterns, market themes or sectors, or to build, fix or explain a scanr.ai scan payload.
---

# scanr.ai stock scanner

scanr.ai scans every U.S.-listed stock against a JSON **scan payload** and returns the matching tickers in one request. Full docs: https://api-docs.scanr.ai/llms.txt (every page is markdown).

## Access

- REST base URL: `https://scanr.ai/api/v2`. Header: `Authorization: Bearer $SCANR_API_TOKEN` (tokens start `scanr_`). JSON in, JSON out.
- MCP: `https://mcp.scanr.ai` (Streamable HTTP, same Bearer header). Tools: `natural_scan`, `refine_payload`, `scan`, `search_securities`, `market_status`, `get_news`, `hot_tickers`, `concept_research` (Power User plan+), `ping`.
- Never print the token or put it in a URL.

## Workflow

1. **Get a payload. Don't write one from scratch.** Either:
   - **generate** it from the user's words: MCP `natural_scan {query}` or `POST /scan/natural {"query": "..."}`. It returns `generated_payload` plus `reasoning.summary` and `reasoning.filters`. It does not run the scan. Or
   - **use the user's own scan**: JSON they exported from the scanr.ai scanner (**Filters → Export filters**) or a saved scan's `payload` from `POST /scan/myscans`. Use it unchanged. It costs no AI credits.
2. **Confirm** by telling the user, in one or two lines, what will be screened (`reasoning.summary`).
3. **Adjust** with MCP `refine_payload {existing_payload, refinement_query}` or `POST /scan/refine`. It keeps unrelated filters and returns `refined_payload`.
4. **Run**: MCP `scan {instructions: payload}` or `POST /scan {"instructions": payload}`. Response: `{tickers, count, cached, scan_id, ...}`: tickers only, in `Sort` order.
5. **Enrich** the top matches if the user needs context: `POST /stocks/get-stock-indicators {"tickers": [...]}` for relative strength (Power User plan+), `search_securities` for names, `get_news` for news.
6. **Report** the count, the top tickers, what the screen required, and, if the market is open, that intraday results are provisional.

Generating (step 1) and refining (step 3) spend AI credits; running a payload doesn't. Keep and reuse payloads. A generated or exported payload is the bare object (`Universe`, `All`, ...); send it as `{"instructions": payload}`.

## Payload shape

```json
{
  "instructions": {
    "Universe": {
      "Exchange": ["nasdaq", "nyse", "amex", "arca", "bats", "bx"],
      "Type": ["cs", "os", "adrc"]
    },
    "All": [
      {
        "Stock": {
          "MarketCap": [
            { "State": { "Value": { "Lower": { "Operator": "gte", "Value": 2000000000 } } } }
          ]
        },
        "Technical": {
          "RSI": [
            {
              "Timeframe": "1d",
              "Inputs": ["bar_close"],
              "Params": { "Period": { "Value": 14 } },
              "Returns": { "Want": { "RSI": { "Value": { "LessThan": 30 } } } }
            }
          ],
          "SMA": [
            {
              "Timeframe": "1d",
              "Inputs": ["bar_close"],
              "Params": { "Period": { "Value": 200 } },
              "Returns": { "Want": { "SMA": { "Price": { "Comparison": { "LessThan": true } } } } }
            }
          ]
        },
        "Indicator": {
          "RelativeStrengthMkt": [
            { "Returns": { "Want": { "Value": { "GreaterThanOrEqual": 70 } } } }
          ]
        }
      }
    ],
    "Sort": { "field": "market_cap", "direction": "desc" }
  }
}
```

(Large caps above the 200-day SMA, RSI(14) under 30, RS 70+.)

## Rules that models get wrong

- **Always set `Universe.Exchange` and `Universe.Type`** as above. Empty `Exchange` admits OTC; empty `Type` includes ETFs.
- **Groups:** `All` = every filter in the group must match; `Any` = at least one; `Exclude` = remove matches. Result = All ∪ Any − Exclude. An `All` and an `Any` group **union**, they don't intersect. Default to one `All` group.
- **Every `Technical`, `CandlestickPattern` and `ChartPattern` row needs `Timeframe`**: one of `1m 2m 3m 4m 5m 10m 15m 20m 30m 1hr 2hr 4hr 1d 2d 3d 4d 1wk 1mo`. Not `1w`, not `1h`. Chart patterns take only `5m`, `1hr`, `1d`.
- **`Want` is keyed by the study's plot name**, from the catalog's `Returns.Plot`: `SMA`→`SMA`, `RSI`→`RSI`, `MACD`→`MACD`/`Signal`/`MACDHist`, `BBANDS`→`Upper`/`Middle`/`Lower`, `STOCH`→`SlowK`/`SlowD`, `RELVOL_STDDEV`→`VALUE`.
- **Three ways to compare a study:** `{"Value": {"LessThan": 30}}` (a number); `{"Price": {"Comparison": {"LessThan": true}}}` (reads *study < price*, so this means price **above** the study); `{"Study": {"CrossesAbove": {"SMA": [ <inner study with "Returns": {"Want": {"SMA": {"PlotChild": true}}}> ]}}}` (another study; add `"Within": 5` to the outer row for "in the last 5 bars").
- **Comparators:** `GreaterThan`, `GreaterThanOrEqual`, `LessThan`, `LessThanOrEqual`, `EqualTo`, `NotEqualTo`, `CrossesAbove`, `CrossesUnder`.
- **Stock numeric ranges:** `{"State": {"Value": {"Lower": {"Operator": "gte", "Value": N}, "Upper": {"Operator": "lt", "Value": M}}}}`. `Lower` takes `gt`/`gte`, `Upper` takes `lt`/`lte`. Market cap in dollars.
- **Near a level:** `"Week52High": [{"State": {"Price": {"Comparison": {"EqualTo": true}, "WithinPercent": 15}}}]`.
- **Sector/Industry:** `"Sector": [{"State": {"Value": ["Healthcare"]}}]`. Names from `GET /stocks/sectors`, `GET /stocks/industries`. There is no "Technology" sector.
- **Indicators** (`RelativeStrengthMkt`/`Sector`/`Industry` 1–99, `GroupStrength` −100–100, `TrendEfficiency` 0–100, `RegimeExtension` −100–100): `{"Returns": {"Want": {"Value": {"GreaterThanOrEqual": 80}}}}`.
- **Fundamentals:** `{"State": {"FilingType": "10q"|"10k", "Within": 1, "Lag": 0, "WantsValue": {"SingleValue": {"GreaterThanOrEqual": true, "Value": 0.25}}}}`. Growth rates are fractions (0.25 = 25%). `Lag: 4` on a `10q` = same quarter last year.
- **Countries** are lower-case ISO codes (`us`), and `Country` removes every ETF (funds have no country). **Themes** are keys from `GET /scan/universe-themes`; an unknown key silently matches nothing.
- Send plain JSON numbers. Leave out catalog echo fields (`DisplayName`, `Type`, `InstructionType`, `Description`), except `DisplayName` on `ChartPattern` rows, which is required.
- Limits: 200 filter rows, 1 MiB.

## Discovering filters

`GET https://scanr.ai/api/v2/scan/instructions` (no token needed) returns the whole catalog: `Stock`, `Technical` (100+ studies), `Indicator`, `Fundamental` (300+ metrics), `CandlestickPattern` (60+), `ChartPattern` (17), `Zone`, and `Reference` (timeframes, operators, study inputs such as `bar_close`, `bar_volume`, `bar_dollar_volume`). Each technical entry's `Params` gives defaults and bounds, and `Returns.Plot` gives the plot names. Fetch once and cache.

## Errors

`400`: the message names the bad field; fix it, don't regenerate. `401`: token problem. `403`: API plan inactive, plan too low for that endpoint, missing `write` scope, or personal-data access disabled. `429`: rate limit or AI credits; wait at least a minute. Limits are per endpoint: Starter 30/min, Power User 60/min, Business 120/min.

## Other endpoints worth knowing

- `POST /stocks/relative-strength {"scope": "market"|"sector"|"industry", "value": "<name>", "limit": 20}`: ranked RS leaders (Power User+).
- `POST /technicals/technical/{category}/{name}` e.g. `/momentum/rsi {"tickers": ["AAPL"], "timeframe": "1d", "params": {"period": 14}}`; `POST /technicals/technical/bulk` for many studies at once (Power User+).
- `GET /stocks/themes`, `GET /stocks/themes/performance/latest`: correlation-based market themes and their performance (Business).
- `POST /scan/save-filters` (needs `write`), `POST /scan/myscans`, `POST /scan/paginated-scan-events`: saved scans and their alerts.
