amaprice
v1.0.17
Published
CLI tool to scrape and track Amazon product prices
Maintainers
Readme
AMAprice.sh - terminal first e-commerce price tracking
amaprice is a terminal-first CLI to check e-commerce prices, track products, and build shared price history automatically.
It starts with Amazon support and will expand to Walmart and other major e-commerce stores.

Install
Requires Node.js >=20.
npm install -g amapriceFirst install downloads Playwright Chromium (via npm postinstall).
You can also run it without global install:
npx amaprice price "https://www.amazon.de/dp/B0DZ5P7JD6"Quickstart
# one-shot lookup (no subscription)
amaprice price "https://www.amazon.de/dp/B0DZ5P7JD6"
# start tracking + subscribe current user + auto-start background collector
amaprice track B0DZ5P7JD6 --tier daily
# or subscribe directly to an existing shared catalog product
amaprice subscribe B0DZ5P7JD6
# show history
amaprice history B0DZ5P7JD6 --limit 30
# list tracked products
amaprice list
# list all subscriptions for current user (including paused)
amaprice subscriptions --all
# stop one product subscription for current user
amaprice unsubscribe B0DZ5P7JD6
# stop/start background collector service
amaprice background off
amaprice background onInput Modes
price and track accept input in three ways:
- direct argument (
amaprice price <url-or-asin>) - piped stdin (
echo "<url-or-asin>" | amaprice price) - interactive prompt (run command without argument)
Short links from Amazon apps (for example amzn.eu, amzn.to, a.co) are accepted and resolved automatically.
Commands
| Command | Description |
|---|---|
| amaprice [url\|asin] | Shortcut for amaprice price [url\|asin] |
| amaprice price [url\|asin] | One-shot lookup (no subscription) and silent history insert |
| amaprice track [url\|asin] | Track product + subscribe current user + auto-start background (--tier, --manual-tier, --auto-tier, --inactive) |
| amaprice subscribe [url\|asin] | Subscribe current user to shared product catalog entry |
| amaprice unsubscribe <url\|asin> | Disable current user subscription |
| amaprice subscriptions | List user subscriptions with latest known prices |
| amaprice history <url\|asin> | Show history (--limit N) |
| amaprice list | List current user subscriptions + latest price (default view) |
| amaprice list --global | List global shared catalog tracked products |
| amaprice sync --limit <n> | Run background sync for due products |
| amaprice background <on\|off\|status> | Manage true background collector service |
| amaprice tier <url\|asin> <hourly\|daily\|weekly> | Set tier/status (--auto, --manual, --activate, --deactivate) |
All commands support --json.
Most Common User Flows
One-time Price Check (No Subscription)
amaprice price B0DZ5P7JD6This returns the current price immediately and does not create a user subscription.
Subscribe + Run in Background
amaprice track B0DZ5P7JD6
amaprice background status --jsontrack (and subscribe) auto-starts the background collector on macOS (launchd).
You can close your terminal after this; the service keeps running.
Stop Product + Stop Background Service
amaprice unsubscribe B0DZ5P7JD6
amaprice background offBackground Service (Auto)
track and subscribe automatically ensure a true background collector service is running.
This service:
- keeps running after terminal close
- survives shell sessions
- polls queue jobs every
180sby default - currently uses
launchdon macOS
Simple control commands:
amaprice background status
amaprice background on
amaprice background offCurrently Supported Store
Amazon domains:
amazon.de, amazon.com, amazon.co.uk, amazon.fr, amazon.it, amazon.es, amazon.nl, amazon.co.jp, amazon.ca, amazon.com.au, amazon.in, amazon.com.br
Outlook
- [x] Amazon (live now)
- [ ] Walmart (next)
- [ ] More major e-commerce stores after Walmart
Goal: bring multi-store price tracking into one terminal-first workflow.
Testing
Run regression and parser tests:
npm testTiered Background Model
Each product has:
tier:hourly,daily, orweeklytier_mode:autoormanualnext_scrape_at: when the worker should scrape next
How tiers are determined in auto mode:
hourly: 2+ price changes in 48h, or >=5% change across 7 daysdaily: normal active productsweekly: no observed change in 30 days
Worker behavior:
- claims due products
- scrapes with Playwright
- writes
price_history - writes
scrape_attemptstelemetry for block/error monitoring - resets/backs off on failures
- updates next run with jitter
Database Migration (Supabase)
Run this SQL in Supabase SQL Editor:
supabase/migrations/20260220_add_tier_scheduler.sql
supabase/migrations/20260220_add_scrape_attempts.sql
supabase/migrations/20260220_add_worker_health_view.sql
supabase/migrations/20260220_grant_worker_health_select.sql
supabase/migrations/20260220_add_price_history_currency.sql
supabase/migrations/20260222_add_hybrid_orchestration.sql
supabase/migrations/20260223_enforce_collector_first_claiming.sql
supabase/migrations/20260225_add_web_track_requests.sql
These migrations add tier fields, indexes, telemetry, worker health rollups, price_history.currency, collector orchestration tables/functions, strict collector-first claim policy, and website intake request tracking.
Note: these files are additive migrations and expect existing products + price_history tables.
Block Detection Queries
Products currently failing or likely blocked:
select asin, tier, consecutive_failures, last_error, last_scraped_at, next_scrape_at
from products
where consecutive_failures >= 3
or last_error ilike '%captcha%'
or last_error ilike '%robot%'
or last_error ilike '%503%'
order by consecutive_failures desc, next_scrape_at asc;Hourly block-rate from telemetry:
select
date_trunc('hour', scraped_at) as hour,
count(*) as total,
sum(case when blocked_signal then 1 else 0 end) as blocked,
round(100.0 * sum(case when blocked_signal then 1 else 0 end) / nullif(count(*), 0), 2) as blocked_pct
from scrape_attempts
where scraped_at >= now() - interval '24 hours'
group by 1
order by 1 desc;Single-row worker health view:
select * from worker_health;Local/Worker Environment
Use your own Supabase project for isolated data:
export SUPABASE_URL="https://<project-ref>.supabase.co"
export SUPABASE_KEY="<anon-or-service-role-key>"Environment variables used by the npm package:
| Variable | Default | Used by | Notes |
|---|---|---|---|
| SUPABASE_URL | built-in public project URL | CLI + worker | Override for your own Supabase project |
| SUPABASE_KEY | built-in public anon key | CLI + worker | Preferred variable name |
| SUPABASE_ANON_KEY | none | CLI + worker | Alias fallback if SUPABASE_KEY is unset |
| SYNC_INTERVAL_MINUTES | 5 | src/worker.js | Worker loop interval |
| SYNC_LIMIT | 20 | src/worker.js, amaprice sync --limit | Max due products per run |
| SYNC_RUN_ONCE | 0 | src/worker.js | Set 1 for single run and exit |
| AMAPRICE_AUTO_BACKGROUND | 1 | track, subscribe | Set 0 to disable auto background startup |
| COLLECTOR_POLL_SECONDS | 180 | background collector service | Queue poll interval |
| COLLECTOR_LIMIT | 10 | background collector service | Max claimed jobs per poll |
| VISION_FALLBACK_ENABLED | 0 | src/extractors/pipeline.js | Enable screenshot + vision fallback when HTML/JSON extraction fails |
| OPENROUTER_API_KEY | none | src/extractors/vision.js | Preferred vision provider key |
| VISION_MODEL | google/gemini-3-flash-preview | src/extractors/vision.js | OpenRouter model ID for vision extraction |
| VISION_PROVIDER | auto | src/extractors/vision.js | Optional force value: openrouter or openai |
| OPENROUTER_HTTP_REFERER | none | src/extractors/vision.js | Optional OpenRouter attribution header |
| OPENROUTER_TITLE | none | src/extractors/vision.js | Optional OpenRouter attribution header |
| VISION_GUARDRAIL_ENABLED | 1 | src/extractors/pipeline.js | Reject suspicious vision outputs before DB writes |
| VISION_GUARDRAIL_MIN_CONFIDENCE | 0.92 | src/extractors/pipeline.js | Minimum confidence required for vision price acceptance |
| VISION_GUARDRAIL_MAX_REL_DELTA | 0.5 | src/extractors/pipeline.js | Max relative delta vs last known price before rejecting vision price |
| OPENAI_API_KEY | none | src/extractors/vision.js | Legacy fallback if OPENROUTER_API_KEY is unset |
For production background workers, prefer the Supabase service role key.
Website API runtime (Next.js server routes):
| Variable | Default | Used by | Notes |
|---|---|---|---|
| SUPABASE_URL | none | website API routes | Server-side Supabase project URL |
| SUPABASE_SERVICE_ROLE_KEY | none | website API routes | Required for secure writes (/api/v1/track-requests) |
| WEB_TRACK_RATE_LIMIT_WINDOW_SECONDS | 300 | website API routes | Sliding rate-limit window |
| WEB_TRACK_RATE_LIMIT_MAX_REQUESTS_PER_IP | 8 | website API routes | Rate-limit threshold per IP hash |
| WEB_TRACK_RATE_LIMIT_MAX_REQUESTS_PER_VISITOR | 12 | website API routes | Rate-limit threshold per visitor cookie |
| WEB_TRACK_IP_HASH_PEPPER | amaprice-default-pepper | website API routes | Pepper for deterministic IP hashing |
| TURNSTILE_SECRET_KEY | none | website API routes | Optional CAPTCHA verification for intake endpoint |
Railway Worker Deployment
This repo includes:
src/worker.js(long-running loop worker)railway.json+Dockerfile(Playwright-ready runtime)
Steps:
- Create a Railway project from this repo.
- Add env vars:
SUPABASE_URL,SUPABASE_KEY. - Optional env vars:
SYNC_INTERVAL_MINUTES=5SYNC_LIMIT=20VISION_FALLBACK_ENABLED=1OPENROUTER_API_KEY=<your-openrouter-key>VISION_MODEL=google/gemini-3-flash-previewVISION_GUARDRAIL_ENABLED=1VISION_GUARDRAIL_MIN_CONFIDENCE=0.92VISION_GUARDRAIL_MAX_REL_DELTA=0.5
- Ensure builder is Dockerfile (root
Dockerfile). - Deploy.
- Confirm logs show
[worker] processed=....
If Railway still uses Railpack instead of Dockerfile, set builder to Dockerfile manually in Railway service settings and redeploy.
One-shot run for testing:
npm run worker:onceVercel Website Deployment (amaprice.sh)
The website is a server-capable Next.js app in website/ with API routes.
Steps:
- Import the repo in Vercel.
- Leave the project at repo root (deployment is controlled by root
vercel.json). - Set website env vars:
SUPABASE_URLSUPABASE_SERVICE_ROLE_KEYNEXT_PUBLIC_GOOGLE_SITE_VERIFICATION(for Google Search Console verification meta tag)
- Deploy.
- Add domain
amaprice.shin Vercel Domains and assign to this project. - Set
www.amaprice.shredirect toamaprice.sh.
Website API Endpoints
POST /api/v1/track-requests- submit Amazon URL/ASIN intake requestGET /api/v1/track-requests/:id- poll request state (queued,collecting,live, ...)GET /api/v1/products- live tracked products for website explorerGET /api/v1/products/:productId/history- historical points for one productGET /api/v1/prices/recent- recent global price pointsGET /api/v1/worker-health- worker health rollup row
Local website development:
cd website
npm install
npm run devSEO + LLM Discoverability
The website includes:
https://amaprice.sh/robots.txt(open crawl policy, no root blocking)https://amaprice.sh/sitemap.xml(canonical URLs for Google indexing)https://amaprice.sh/llms.txt(concise LLM index)https://amaprice.sh/llms-full.txt(extended technical guide)
Google Search Console
- Open https://search.google.com/search-console
- Add property
https://amaprice.sh - Choose HTML meta-tag verification
- Set
NEXT_PUBLIC_GOOGLE_SITE_VERIFICATIONwith the provided token - Deploy the website
- In Search Console, submit
https://amaprice.sh/sitemap.xml - Request indexing for key pages if needed
Community Price Data
amaprice contributes anonymized price snapshots (title, ASIN, price, timestamp) to a shared dataset.
No personal/device data is stored.
License
MIT
