Prisync Alternative — Competitor Price & Stock Monitor avatar

Prisync Alternative — Competitor Price & Stock Monitor

Pricing

from $0.00005 / actor start

Go to Apify Store
Prisync Alternative — Competitor Price & Stock Monitor

Prisync Alternative — Competitor Price & Stock Monitor

Monitor competitor prices and stock across Shopify stores and product pages. Track price and availability changes with SKU matching, change-only runs, datasets, schedules, webhooks, and pay-per-event pricing.

Pricing

from $0.00005 / actor start

Rating

0.0

(0)

Developer

Solutions Smart

Solutions Smart

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

11 hours ago

Last modified

Categories

Share

Prisync Alternative: competitor price and stock monitor

Monitor competitor prices and stock on Shopify and product pages. Pay per check, get change webhooks, and keep the results in your Apify account. The Actor extracts product identity, price, currency, image, and availability, then compares each check with the previous snapshot.

Use it for scheduled competitor price monitoring, stock alerts, product catalog checks, and webhook-based pricing workflows. There is no monthly seat. Enter product URLs or a Shopify store domain, choose the output mode, and run the Actor.

The extraction harness was checked against TEST.md, with 100% parse success and 100% usable-price recovery in the recorded run.

What the Actor does

  • Checks individual product pages or discovers a Shopify catalog from /products.json and product sitemaps.
  • Extracts product data from JSON-LD, Shopify data, Open Graph and other metadata, then uses DOM signals as a last resort.
  • Matches products across runs by SKU, MPN, GTIN/EAN, or canonical URL.
  • Reports PRICE_DROP, PRICE_RISE, OOS, BACK_IN_STOCK, NEW, and UNCHANGED events.
  • Records BLOCKED, LOGIN_REQUIRED, EMPTY, and PARSE_ERROR failures instead of inventing product data.
  • Stores snapshots in the default key-value store so scheduled runs can compare against the previous check.
  • Sends a batch of change rows to an optional webhook.
  • Uses Apify Proxy and optional Unblocker fallback for sites that need a residential route or browser challenge recovery.
  • Exposes results through the Apify dataset, API, schedules, integrations, and webhooks.
  • Optionally uses Jev to classify ambiguous pages when deterministic extraction cannot identify a product.

Prisync Alternative comparison

This ActorPrisync-style SaaS
BillingPay per product check and change event on ApifyMonthly seat or plan subscription
MonitoringYour product URLs or a Shopify catalogVendor and product watchlists
DeliveryDataset, API, schedules, webhooks, and integrationsSaaS dashboard and plan-dependent exports
Data ownershipResults and snapshots stay in your Apify accountData stays in the vendor workspace

This Actor is a fit when you want programmable output, scheduled runs, and direct access to the collected dataset.

Quick start

  1. Add one or more product URLs in the startUrls field, or enter a Shopify domain in catalogMode.
  2. Choose ALL to receive every check or CHANGES_ONLY to receive only changes and failures.
  3. Set persistState to true for comparisons between runs.
  4. Set a fixed apifyProxyCountry when prices or currencies depend on the visitor's market.
  5. Run the Actor once, then schedule it to run again at the interval you need.

The Apify Console uses request objects for startUrls:

{
"startUrls": [
{ "url": "https://www.cotopaxi.com/products/down-mitten-3" },
{ "url": "https://www.kith.com/products/s57ws0538p7573t4027" },
{ "url": "https://www.uniqlo.com/de/de/products/E476766-000/00" }
],
"matchKey": "AUTO",
"emitMode": "CHANGES_ONLY",
"currencyPreferred": "USD",
"priceDropPct": 2,
"alertOnOos": true,
"alertOnBackInStock": true,
"persistState": true,
"proxyConfiguration": {
"useApifyProxy": true,
"apifyProxyGroups": ["RESIDENTIAL"],
"apifyProxyCountry": "US"
}
}

For a Shopify catalog, use catalogMode instead of startUrls:

{
"catalogMode": "cotopaxi.com",
"maxItems": 400,
"emitMode": "CHANGES_ONLY",
"persistState": true
}

Input settings

FieldDescription
startUrlsProduct page request objects. Required unless catalogMode is set.
catalogModeShopify store domain for catalog discovery.
matchKeyAUTO, SKU, MPN, EAN, or TITLE_FUZZY. AUTO uses the strongest available identifier and falls back to URL identity when no identifier is available. TITLE_FUZZY uses title similarity for match confidence.
emitModeALL or CHANGES_ONLY.
currencyPreferredFills a missing currency. It does not convert prices.
priceDropPctMinimum percentage drop needed for PRICE_DROP.
priceRisePctMinimum percentage rise needed for PRICE_RISE.
alertOnOosEnables OOS events. Defaults to true.
alertOnBackInStockEnables BACK_IN_STOCK events. Defaults to true.
maxItemsMaximum product pages checked in one run. Defaults to 1000.
maxConcurrencyNumber of pages checked in parallel. Defaults to 3.
requestTimeoutSecsPer-page timeout. Defaults to 45 seconds.
proxyConfigurationApify Proxy, custom proxy URLs, or direct access.
unblockerFallbackRetries blocked pages through Unblocker. Requires Apify Proxy and a two-letter apifyProxyCountry.
maxUnblockerRequestsMaximum product URLs sent to the fallback. Defaults to 10.
useJevOptional paid Jev recovery for ambiguous pages after deterministic extraction fails. Defaults to false.
webhookUrlReceives a JSON batch when the run emits change events.
persistStateStores snapshots for future comparisons. Defaults to true.
debugEnables additional diagnostic logging.

Output

The default dataset contains one row per product check or failure. A successful product row looks like this:

{
"stableId": "5c6b3dc939cff6e3a932",
"anchor": "sku",
"url": "https://www.cotopaxi.com/products/down-mitten-3",
"canonicalUrl": "https://www.cotopaxi.com/products/down-mitten-3",
"title": "Down Mitten",
"brand": "Cotopaxi",
"sku": "CMS12958",
"price": 26,
"salePrice": 26,
"currency": "USD",
"availability": "IN_STOCK",
"changeType": "PRICE_DROP",
"pricePrevious": 32.5,
"priceDelta": -6.5,
"priceDeltaPct": -20,
"availabilityPrevious": "IN_STOCK",
"matchConfidence": 1,
"priceSource": "jsonld",
"scrapedAt": "2026-09-15T10:12:00.000Z"
}

Failed checks are still emitted so a scheduled workflow does not look successful when a site becomes unavailable:

{
"stableId": "empty:https://example.com/product",
"anchor": "url",
"url": "https://example.com/product",
"checkStatus": "FAIL",
"changeType": "PARSE_ERROR",
"emptyReason": "PARSE_ERROR",
"errorMessage": "no product identifiers found; page is not a confirmed removal"
}

When CHANGES_ONLY finds no changes, the Actor emits one free summary row:

{
"changeType": "NO_CHANGES_SUMMARY",
"runId": "HnoZxeqjqG4tFWwzA",
"stateNamespace": "default",
"emittedRows": 0,
"productChecks": 12,
"unchangedCount": 12,
"changedCount": 0,
"failedCount": 0,
"urlCount": 12
}

Webhook example

When a run detects changes, webhookUrl receives a JSON batch similar to this:

{
"type": "solutionssmart-price-monitor",
"runId": "HnoZxeqjqG4tFWwzA",
"stateNamespace": "default",
"changedCount": 1,
"scrapedAt": "2026-09-18T21:22:38.800Z",
"items": [
{
"stableId": "5c6b3dc939cff6e3a932",
"changeType": "PRICE_DROP",
"title": "Down Mitten",
"price": 26,
"pricePrevious": 32.5,
"currency": "USD",
"url": "https://www.cotopaxi.com/products/down-mitten-3"
}
]
}

Change detection and state

The Actor writes a snapshot for each tracked product to the default key-value store. A snapshot contains the last known price, availability, title, identifiers, currency, canonical URL, and update time.

Price changes require matching, known currencies. The Actor does not convert USD, EUR, GBP, or other currencies. Stock changes can still be reported when currencies differ. A product with no price can still produce a valid availability check when stock evidence is clear.

The first successful check for a product is NEW. Later runs use the stable identity and previous snapshot to produce change events. Set persistState to false when you want every run to start with a fresh baseline.

Pricing

The Actor uses Apify resources according to your account and configuration. A run can consume compute units, proxy traffic, browser requests, and Unblocker usage when enabled.

This Actor supports Pay per Event configuration for product-check, change-event, jev-recovery, and the run-start event. Failed checks, summaries, and NO_CHANGES_SUMMARY rows are not intended to be billed as dataset items. Jev is opt-in, so ordinary checks do not incur a Jev event. Review the Actor's Pricing tab and your Apify usage before running large catalogs.

Recommended event titles and descriptions:

EventTitleDescription
product-checkProduct checkOne successfully parsed product URL, including price, stock, identity, and comparison with stored state.
change-eventPrice or stock changeOne detected new product, price change, stock change, availability change, or product replacement.
jev-recoveryJev page classificationOne optional Jev request used to classify an ambiguous page after deterministic extraction could not identify a product.

With low-cost beta pricing, a starting point is $0.003 per product-check, $0.001 per change-event, and $0.005 per jev-recovery. Adjust after checking TypeSafe usage and Apify compute costs.

Unblocker is an optional paid fallback. It can make an additional browser request for a selected URL and may generate additional proxy usage. Keep maxUnblockerRequests low while testing.

MAP and minimum-price monitoring

The Actor currently supports relative price thresholds through priceDropPct and priceRisePct. For an absolute MAP or minimum-price rule, run the Actor with emitMode: "ALL", read the dataset through the Apify API, and filter rows where price is below your MAP value. This keeps the scrape and the business rule separate while preserving the raw observation.

{
"startUrls": [
{ "url": "https://www.cotopaxi.com/products/down-mitten-3" }
],
"emitMode": "ALL",
"persistState": true,
"priceDropPct": 1
}

Proxy and troubleshooting

The Actor stops with an Unblocker configuration error

Set both of these values when unblockerFallback is true:

{
"unblockerFallback": true,
"proxyConfiguration": {
"useApifyProxy": true,
"apifyProxyCountry": "US"
}
}

If you do not need Unblocker, set unblockerFallback to false and use direct access or a regular proxy.

The output contains UNKNOWN availability

The page had price or product evidence but no reliable stock signal. This is intentional. The Actor avoids turning an ambiguous button or out-of-stock phrase into a false alert.

The output contains PARSE_ERROR

The page loaded, but the Actor could not find enough trusted product evidence. Check whether the site needs a residential proxy, whether the product URL is still live, and whether the page uses client-side data that is not exposed to the browser probe.

The output contains BLOCKED or LOGIN_REQUIRED

The site returned a bot challenge, access denial, or account wall. Use a permitted proxy configuration, enable the bounded Unblocker fallback when appropriate, or remove the URL. Do not use the Actor to bypass access controls without authorization.

Compatibility and responsible use

The Actor works best with Shopify, JSON-LD product data, Open Graph metadata, or a visible product price and availability signal. It may need a residential proxy for Amazon, Walmart, eBay, Home Depot, ASOS, Target, Apple, and sites protected by Akamai or Cloudflare.

Check each website's terms, robots rules, and applicable law before monitoring it. Use an appropriate request rate and proxy configuration. Do not collect personal data or attempt to bypass authentication.

The extraction harness has been checked against 20 real product URLs across 10 domains. The recorded run reached 100% parse success and 100% usable-price recovery; see TEST.md for the URLs, source tiers, limits, and known failures.

FAQ

Can I monitor a whole store?

Yes. Set catalogMode to a Shopify domain and limit the run with maxItems.

Does the Actor convert currencies?

No. It records the currency exposed by the page or uses currencyPreferred when the page omits one. Price comparisons require the previous and current currencies to match.

Does a failed URL stop the whole run?

Individual failures are emitted as rows. The run fails at the end when every requested URL fails, which prevents a completely empty or blocked run from appearing successful.

Can I use the dataset through an API?

Yes. Apify exposes the default dataset and run data through its API, SDKs, schedules, and integrations.

How do I report a problem?

Include the Actor run ID, input, failing URL, emptyReason, and the relevant log lines. Do not include proxy credentials, API keys, or private page content.

Local development

Install dependencies and run the regression tests:

npm install
node --test test/changes.test.js test/retrieval.test.js

Run the Actor with the Apify CLI:

$apify run --input-file examples/input-one-off.json

The falsification notes and representative URL checks are in TEST.md.