Tutorial: Find support and resistance levels for any stock or crypto with one API call


Support and resistance are the first lines most traders draw on a chart: the floors where buyers keep stepping in, and the ceilings where sellers keep taking over. Drawing them by hand is slow, a bit subjective, and impossible to repeat across a whole watchlist every day.

The Support & Resistance indicator (supportresistance) does it for you, for any crypto pair or US stock on TAAPI.IO, on any timeframe. One request tells you where the next floor and ceiling are, how far away they are in percent, and gives you every other level around price as well.

This tutorial explains what the indicator returns, walks through two real examples with charts, Bitcoin and NVIDIA, and ends with two small scripts you can copy and run.

What the indicator does

The indicator looks for swing highs and swing lows: candles where price turned and then moved away. When price turns at roughly the same price more than once, those swings are merged into one level. Each level is then labelled by where it sits right now: below the current price it’s support, above it it’s resistance.

One request returns:

  • The nearest support and resistance (nearest_support, nearest_resistance), with their distance from price in percent. These are always included.
  • The current price (current_price), so you don’t need a second request to work out the distances.
  • Every level, when you add results=max: its price, whether it’s support or resistance now (role), how many times price turned there (touches), when it last did, how far away it is, and whether price has closed through it since (broken).

So a single call answers the three questions traders ask first: where is the next floor, where is the next ceiling, and how much room is there to each?

Your first request

curl -G https://v2.taapi.io/indicator/supportresistance \
  -H "Authorization: Bearer YOUR_API_KEY" \
  --data-urlencode "exchange=binance" \
  --data-urlencode "symbol=BTCUSDT" \
  --data-urlencode "timeframe=1d" \
  --data-urlencode "lookback=10" \
  --data-urlencode "lookforward=10" \
  --data-urlencode "results=max"

Why these settings? lookback=10 and lookforward=10 mean a swing only counts if it’s the highest or lowest candle of 21 days, about three weeks. That’s what we recommend for daily levels: it keeps the swings traders watch over several weeks and drops the day-to-day noise. results=max returns every level instead of just one.

This is a real response from 10 November 2026, shortened to the two nearest levels. With results=max, every array has one entry per level, in the same order:

{
  "line_type": ["support", "resistance"],
  "left_timestamp": [1741651200, 1634688000],
  "right_timestamp": [1794268800, 1794268800],
  "price": [78430, 66556.16],
  "pattern_index": [7, 1],
  "role": ["resistance", "support"],
  "touches": [2, 4],
  "last_touch_timestamp": [1743984000, 1784592000],
  "distance": [4189.779999999999, -7684.059999999998],
  "distance_percent": [5.6435446985474975, -10.350265664622219],
  "broken": [true, true],
  "broken_timestamp": [1744070400, 1787097600],
  "current_price": 74240.22,
  "nearest_support": 66556.16,
  "nearest_support_distance_percent": -10.350265664622219,
  "nearest_resistance": 78430,
  "nearest_resistance_distance_percent": 5.6435446985474975,
  "timestamp": [1794268800]
}

Here’s how to read it:

  • nearest_resistance is 78,430, 5.6% above the current price of 74,240. nearest_support is 66,556, 10.4% below.
  • In the arrays, each position is one level. The first level is at 78,430, sits above price (role: "resistance") and was formed by 2 turns. The second, at 66,556, is below price (role: "support") and has been touched 4 times, which is why it ranks first (pattern_index: 1).
  • Use role, not line_type. line_type says whether the level was built from swing lows or swing highs. 78,430 was built from lows in spring 2025, so it’s still "support" there, but price is below it now, so its role is "resistance". Old floors often become new ceilings, and role already accounts for that.

Example 1: Bitcoin (BTCUSDT)

Here are the levels from the response above, drawn on a weekly Bitcoin chart:

BTCUSDT weekly candles with the support and resistance levels returned on 10 November 2026 Price at 74,240. resistance 85,129, 14.7% above. resistance 81,447, 9.7% above. Nearest resistance 78,430, 5.6% above. Nearest support 66,556, 10.4% below. support 62,824, 15.4% below. 60k 70k 80k 90k 100k 110k 120k 130k Mar May Jul Sep Nov Jan 2026 Mar May Jul Sep Nov 85,129 +14.7% Resistance 81,447 +9.7% Resistance 78,430 +5.6% Nearest resistance 66,556 −10.4% Nearest support 62,824 −15.4% Support 74,240 Price now Oct 2025 high 126,200 Feb 2026 low 60,000 Near the 2021 peak: capped pricein July, support since August BTCUSDT · Binance · weekly candles · levels from timeframe=1d, lookback=10, lookforward=10 · 10 Nov 2026
Solid lines are the nearest support and resistance; dashed lines are other levels. Circles mark the first and last touch of each level that falls inside the chart.
Level Price From price Where it comes from
Resistance 85,129 +14.7% Lows of the December 2025 range, now overhead
Resistance 81,447 +9.7% Capped rallies in May and September 2026
Nearest resistance 78,430 +5.6% Two lows in March and April 2025
Current price 74,240   Latest daily candle
Nearest support 66,556 −10.4% Near the 2021 high; 4 touches, the strongest level in the list
Support 62,824 −15.4% Lows in February and August 2026, never closed through

How to read this: Bitcoin topped near 126,200 in October 2025, fell to 60,000 in February and has traded in a wide 58,000–87,000 range since. At 74,240 it sits between two levels. The first ceiling is 78,430, 5.6% higher. The first floor is 66,556, 10.4% lower, and it’s the most-tested level on the chart: it formed near the 2021 high, capped price again in July 2026, and turned into support when Bitcoin broke above it in August.

That gives a trader a quick sense of the room on each side: about 5.6% up to the first ceiling, and about 10.4% down to the first floor. Above 78,430, the next ceilings are 81,447 and 85,129, both of which have stopped rallies this year. Below 66,556 sits 62,824, the only nearby level that price has never closed through.

Example 2: NVIDIA (NVDA)

The same request works for US stocks. Just use exchange=stocks:

curl -G https://v2.taapi.io/indicator/supportresistance \
  -H "Authorization: Bearer YOUR_API_KEY" \
  --data-urlencode "exchange=stocks" \
  --data-urlencode "symbol=NVDA" \
  --data-urlencode "timeframe=1d" \
  --data-urlencode "lookback=10" \
  --data-urlencode "lookforward=10" \
  --data-urlencode "results=max"
NVDA weekly candles with the support and resistance levels returned on 10 November 2026 Price at 179.56. resistance 190.20, 5.9% above. Nearest resistance 182.86, 1.8% above. Nearest support 176.89, 1.5% below. support 170.65, 5.0% below. 160 170 180 190 200 210 220 230 240 250 Jul Sep Nov Jan 2026 Mar May Jul Sep Nov 190.20 +5.9% Resistance 182.86 +1.8% Nearest resistance 176.89 −1.5% Nearest support 170.65 −5.0% Support 179.56 Price now October high 243 9 Nov low 170.24 bounced at 170.65 NVDA · US stocks · weekly candles · levels from timeframe=1d, lookback=10, lookforward=10 · 10 Nov 2026
The shaded area is the winter range where these levels formed. Taken at 11:04 UTC on 10 November 2026, before the US open, so the current price includes pre-market trading.
Level Price From price Where it comes from
Resistance 190.20 +5.9% Tops in December 2025 and January 2026
Nearest resistance 182.86 +1.8% Turned price down in July 2025 and March 2026
Current price 179.56   Latest daily candle, pre-market
Nearest support 176.89 −1.5% Lows in October and November 2025
Support 170.65 −5.0% Lows in December 2025 and February 2026

How to read this: NVIDIA ran up to about 243 in October, then fell hard and is now back in the 170–190 range it traded in last winter. That old range left clear marks. Price is squeezed between a ceiling at 182.86 and a floor at 176.89, only about 3.3% apart. On 9 November the stock dipped to 170.24, right at the next floor of 170.65, and bounced. Many traders would wait for a daily close outside the 176.89–182.86 band: above it, the next ceiling is 190.20; below it, 170.65 comes back into play.

You’ll notice all four NVDA levels show broken: true in the response. That only means price has closed through each of them at some point. Levels that price keeps returning to still matter, which is why the nearest_* fields include them.

What if there’s no level above price?

Apple is a good example. On the same day, AAPL traded at an all-time high, so there was no swing high above price to build a resistance level from:

{
  "current_price": 351.248,
  "nearest_support": 341.25,
  "nearest_support_distance_percent": -2.8464219013346668,
  "nearest_resistance": null,
  "nearest_resistance_distance_percent": null
}

nearest_resistance is null, and so is its distance. The same can happen to support after a big sell-off to new lows. Always check for null before you use either value, as the scripts below do.

Script 1: Nearest levels for a watchlist (Python)

This prints the nearest support and resistance for a mix of crypto pairs and stocks:

import requests

API_KEY = 'YOUR_API_KEY'
WATCHLIST = [('binance', 'BTCUSDT'), ('binance', 'ETHUSDT'), ('stocks', 'NVDA'), ('stocks', 'AAPL')]


def fmt(price, pct):
    if price is None:
        return 'none found'.ljust(22)
    return f'{price:>10,.2f} ({pct:+.1f}%)'.ljust(22)


for exchange, symbol in WATCHLIST:
    r = requests.get(
        'https://v2.taapi.io/indicator/supportresistance',
        headers={'Authorization': f'Bearer {API_KEY}'},
        params={'exchange': exchange, 'symbol': symbol, 'timeframe': '1d',
                'lookback': 10, 'lookforward': 10},
    )
    sr = r.json()
    line = (f"{symbol:<8} {sr['current_price']:>10,.2f}   "
            f"support {fmt(sr['nearest_support'], sr['nearest_support_distance_percent'])} "
            f"resistance {fmt(sr['nearest_resistance'], sr['nearest_resistance_distance_percent'])}")
    print(line.rstrip())

When we ran it, the output looked like this:

BTCUSDT   74,240.22   support  66,556.16 (-10.4%)    resistance  78,430.00 (+5.6%)
ETHUSDT    2,091.38   support   1,993.30 (-4.7%)     resistance   2,225.23 (+6.4%)
NVDA         179.56   support     176.89 (-1.5%)     resistance     182.86 (+1.8%)
AAPL         351.25   support     341.25 (-2.8%)     resistance none found

It makes one request per symbol. US stocks need the Pro plan or higher, which allows 30 requests per 15 seconds, so a watchlist this size runs comfortably. On the free plan, stick to crypto and one request every 15 seconds; see rate limits.

Script 2: A level ladder for one symbol (Node.js)

This lists every level within 20% of price, from the highest to the lowest, with the current price in between:

const API_KEY = 'YOUR_API_KEY';

async function ladder(exchange, symbol, rangePercent = 20) {
  const params = new URLSearchParams({
    exchange, symbol, timeframe: '1d', lookback: 10, lookforward: 10, results: 'max'
  });
  const res = await fetch(`https://v2.taapi.io/indicator/supportresistance?${params}`, {
    headers: { Authorization: `Bearer ${API_KEY}` }
  });
  const sr = await res.json();

  // Turn the parallel arrays into one object per level
  const levels = sr.price.map((price, i) => ({
    price,
    role: sr.role[i],
    touches: sr.touches[i],
    distance: sr.distance_percent[i],
    broken: sr.broken[i]
  }));

  const nearby = levels
    .filter((l) => Math.abs(l.distance) <= rangePercent)
    .sort((a, b) => b.price - a.price);

  console.log(`${symbol} levels within ${rangePercent}% of ${sr.current_price}:`);
  let pricePrinted = false;
  for (const l of nearby) {
    if (!pricePrinted && l.price < sr.current_price) {
      console.log(`  ──── price ${sr.current_price} ────`);
      pricePrinted = true;
    }
    const pct = `${l.distance > 0 ? '+' : ''}${l.distance.toFixed(1)}%`;
    console.log(`  ${l.role.padEnd(10)} ${String(l.price).padStart(9)}  ${pct.padStart(6)}  ` +
      `${l.touches} touches${l.broken ? '' : ', never closed through'}`);
  }
}

ladder('binance', 'BTCUSDT');

Run it with Node.js 18 or newer (node ladder.js). When we ran it, the output looked like this:

BTCUSDT levels within 20% of 74240.22:
  resistance  85129.43  +14.7%  2 touches
  resistance  81447.01   +9.7%  2 touches
  resistance     78430   +5.6%  2 touches
  ──── price 74240.22 ────
  support     66556.16  -10.4%  4 touches
  support     62823.64  -15.4%  2 touches, never closed through

The 62,824 support is the only one marked “never closed through”. That makes it a good candidate if you only want levels that have held every time: filter on broken === false.

Tips

  • Pick the window for your timeframe. lookback=10 and lookforward=10 work well on daily candles. The default of 5 suits intraday timeframes and finds more levels closer to price. Much wider windows leave very few levels.
  • Use role to tell support from resistance, not line_type.
  • Remember the confirmation delay. A swing is only confirmed after lookforward more candles have closed, so with 10 on daily candles, a new level appears 10 days after the swing that forms it.
  • Use closed candles for signals. Add backtrack=1 if you act on the levels, so the current price comes from the last closed candle instead of the one still forming.
  • Combine the level with a trigger. A level tells you where to look. Many traders wait for a daily close beyond it, or a rejection candle at it, before acting.

As always, test a strategy on historical data before you trade it with real money. Support and resistance levels show where price has reacted before, not a guarantee that it will react there again. Nothing in this post is financial advice.

Where to go from here

The Support & Resistance indicator is available now on every plan. Give it a try, and if you build something with it, we’d love to hear about it: get in touch.