Skip to content

Pine Scraper

Overview

The Pine scraper provides authenticated TradingView Pine script management APIs.

✨ Highlight: Pine -> Streamer Custom Indicator Workflow

The primary purpose of Pine support is to power custom indicator workflows in Streamer:

  • Create and maintain your own Pine indicator scripts from Python.
  • Merge multiple indicator calculations into one Pine script.
  • Fetch the merged output through Streamer as a single custom indicator feed.

This lets you centralize strategy logic in one Pine script while consuming the values in your market-data pipeline.

Why teams use this pattern:

  • Some TradingView plans cap concurrent indicator usage (for example, 2 indicators on free usage).
  • A merged custom Pine script can expose multiple signals while occupying one custom indicator stream target.

Current support includes:

  • View your saved Pine scripts
  • Validate Pine source code
  • Create new scripts
  • Edit existing scripts
  • Delete scripts

Cookie authentication is required for all Pine operations.

Common Workflow (Merged Indicators)

Use Pine methods to maintain a script that combines multiple indicator calculations (for example, RSI + EMA + ATR in one script), then fetch that custom indicator through Streamer.

from tv_scraper.scrapers.scripts import Pine
from tv_scraper.streaming import Streamer

pine = Pine(cookie="<TRADINGVIEW_COOKIE>")
streamer = Streamer()

source_code = """
//@version=6
indicator("My Multi Indicator", overlay=false)

rsi = ta.rsi(close, 14)
ema = ta.ema(close, 21)
atr = ta.atr(14)

plot(rsi, title="RSI")
plot(ema, title="EMA")
plot(atr, title="ATR")
"""

# Create or update your script in TradingView
pine.create_script(name="My Multi Indicator", source=source_code)

# Then fetch your saved script id/version pair
saved = pine.list_saved_scripts()
first_script = saved["data"][0]

# Use the corresponding custom indicator id/version in Streamer
result = streamer.get_candles(
    exchange="BINANCE",
    symbol="BTCUSDT",
    timeframe="1h",
    numb_candles=100,
    indicators=[(first_script["id"], str(first_script["version"]))],
)

Note: For custom scripts, use pine.list_saved_scripts() and pass that exact id + version pair into indicators when calling Streamer.get_candles().

Import and Constructor

import os
from tv_scraper.scrapers.scripts import Pine

pine = Pine(
    export_result=False,
    export_type="json",
    timeout=10,
    cookie=os.environ.get("TRADINGVIEW_COOKIE"),
)
Parameter Type Default Description
export_result bool False Export output to file
export_type str "json" Export format: "json" or "csv"
timeout int 10 HTTP timeout in seconds
cookie str \| None None Full TradingView cookie string; falls back to TRADINGVIEW_COOKIE

API

1) list_saved_scripts()

Returns your own saved Pine scripts.

result = pine.list_saved_scripts()

Output example:

{
    "status": "success",
    "data": [
        {
            "id": "USER;cf7b5c71264f45ccb4d298d9ec1eaf88",
            "name": "My script",
            "version": "7.0",
            "modified": 1774357749,
        }
        ...(other scripts)
    ],
    "metadata": {},
    "error": None,
}

2) validate_script(source)

Validates Pine code through TradingView compiler endpoint.

source_code = """
//@version=6
indicator("My Script")
plot(close)
"""

result = pine.validate_script(source_code)

Output example (no errors):

{
    "status": "success",
    "data": None,
    "metadata": {
        "source": "//@version=6\nindicator(\"My Script\")\nplot(close)"
    },
    "error": None,
}

Output example (warnings only):

{
    "status": "success",
    "data": None,
    "metadata": {
        "source": "//@version=6\nindicator(\"My Script\")\nplot(close)",
        "warnings": [
            {
                "message": "Some compiler warning"
            }
        ]
    },
    "error": None,
}

Output example (validation errors):

{
    "status": "failed",
    "data": None,
    "metadata": {
        "errors": [
            {
                "message": "\"sdf\" is not a valid statement.",
                "start": {"line": 8, "column": 1},
                "end": {"line": 8, "column": 3}
            }
        ],
        "warnings": []
    },
    "error": "Pine script validation failed.",
}

Notes:

  • Use this method when you want compiler diagnostics only.
  • This method is optional before create/edit because create/edit already validate internally.

3) create_script(name, source)

Creates a new Pine script.

source_code = """
//@version=6
indicator("My Script")
plot(close)
"""

result = pine.create_script(
    name="My Script",
    source=source_code,
)

Output example:

{
    "status": "success",
    "data": {
        "id": "USER;cf7b5c71264f45ccb4d298d9ec1eaf88",
        "name": "My Script",
        "warnings": []
    },
    "metadata": {
        "name": "My Script",
        "source": "//@version=6\nindicator(\"My Script\")\nplot(close)"
    },
    "error": None,
}

Important behavior:

  • create_script validates source internally before saving.
  • If compiler returns errors, create stops and returns failed response.
  • If compiler returns warnings only, create continues and warnings appear in data["warnings"].

4) edit_script(pine_id, name, source)

Edits an existing Pine script.

updated_source = """
//@version=6
indicator("My Script v2")
plot(close)
"""

result = pine.edit_script(
    pine_id="USER;cf7b5c71264f45ccb4d298d9ec1eaf88",
    name="My Script v2",
    source=updated_source,
)

Output example:

{
    "status": "success",
    "data": {
        "id": "USER;cf7b5c71264f45ccb4d298d9ec1eaf88",
        "name": "My Script v2",
        "warnings": []
    },
    "metadata": {
        "pine_id": "USER;cf7b5c71264f45ccb4d298d9ec1eaf88",
        "name": "My Script v2",
        "source": "//@version=6\nindicator(\"My Script v2\")\nplot(close)"
    },
    "error": None,
}

Important behavior:

  • edit_script validates source internally before saving.
  • If validation fails, edit is blocked.
  • Warnings are returned in data["warnings"] when save succeeds.

5) delete_script(pine_id)

Deletes a script by Pine ID.

result = pine.delete_script("USER;cf7b5c71264f45ccb4d298d9ec1eaf88")

Output example:

{
    "status": "success",
    "data": {
        "id": "USER;cf7b5c71264f45ccb4d298d9ec1eaf88",
        "deleted": True
    },
    "metadata": {
        "pine_id": "USER;cf7b5c71264f45ccb4d298d9ec1eaf88"
    },
    "error": None,
}

Notes:

  • Delete uses a POST request with no payload.
  • TradingView returns "ok" on success.

Error Format

All Pine methods use the standard envelope for failures:

{
    "status": "failed",
    "data": None,
    "metadata": {},
    "error": "TradingView cookie is required for Pine Script operations...",
}

Metadata behavior summary:

  • list_saved_scripts() returns empty metadata.
  • list_saved_scripts() data items include id, name, version, and modified.
  • All other Pine methods return input parameters inside metadata.