Panels return their whole catalogue from one call: action=services. On a busy panel that is hundreds of rows, and scrolling a web table to compare prices gets old fast. Here is a tiny script that turns the response into a CSV you can filter in any spreadsheet.
If you have never used a panel, read this explainer on what an SMM panel is first. It covers the vocabulary used below.
The response shape
Most panels on the /api/v2 pattern return a JSON list like this:
[
{"service": 1, "name": "Instagram Likes", "type": "Default",
"category": "Instagram", "rate": "12.50", "min": "50", "max": "10000",
"refill": true, "cancel": false}
]
rate is usually the price per 1000 in your account currency.
The script
import csv, os, requests
API_URL = os.environ["PANEL_URL"] # e.g. https://example-panel.com/api/v2
API_KEY = os.environ["PANEL_KEY"]
rows = requests.post(API_URL, data={"key": API_KEY, "action": "services"}, timeout=30).json()
fields = ["service", "category", "name", "rate", "min", "max", "refill", "cancel"]
with open("services.csv", "w", newline="", encoding="utf-8") as f:
w = csv.DictWriter(f, fieldnames=fields, extrasaction="ignore")
w.writeheader()
for r in sorted(rows, key=lambda r: (r.get("category", ""), float(r.get("rate", 0)))):
w.writerow(r)
print(f"Wrote {len(rows)} services")
Why sort by category, then rate
- You see the cheapest option in each platform first.
- Duplicate-looking services sit next to each other, so differences in min, max and refill stand out.
- Price changes are easy to spot if you diff two days of CSVs.
Small extras worth adding
- Add a
fetched_atcolumn so old files are obvious. - Keep the key in an environment variable, never in the script.
- Run it once a day with cron and keep the last seven files.
Where I use it
I run this against SMMYodha's panel to keep a quick price sheet, but it works on any panel that follows the same API layout.
Written by MD Fozla Rabbi, SEO Specialist.
Top comments (0)