I wanted to know the moment a specific SHEIN dress dropped below a price I'd set, without checking the page myself like it was 2011. The whole thing took twenty minutes to wire up in n8n against one of my Apify actors, it runs on a schedule for pennies, and it pings me only when a price actually falls. No servers, no cron on a box I have to remember exists, no browser automation to babysit. Here's the exact build.
The shape is five nodes: a schedule trigger fires, an HTTP node runs the SHEIN actor and gets the results back in one call, a code node parses the products, another compares each price against what I stored last run, and a notify node fires only on a drop. Everything talks to the public Apify API, so there's nothing exotic to install.
1. Schedule trigger
Add a Schedule Trigger node. Once a day is plenty for retail pricing, more often than hourly is just noise and wasted runs. Set it to something like every day at 08:00. That's the whole node. n8n handles the cron for you.
2. Run the actor and get results in one shot
Add an HTTP Request node. The trick that keeps this simple is Apify's run-sync-get-dataset-items endpoint: it starts the actor, waits for it to finish, and returns the scraped dataset in the same response. No polling, no run-ID juggling, no second call to fetch results.
- Method:
POST - URL:
https://api.apify.com/v2/acts/native_emblem~shein-product-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN - Body content type:
JSON - Body: the actor's input, the keywords or product URLs you want priced
{
"keywords": ["summer midi dress"],
"maxItems": 25
}
Put your token in n8n credentials rather than pasting it into the URL in the clear, but the shape is exactly that: one POST, token as a query param, actor input as the JSON body. The response is a plain array of product objects. If you're curious what comes back before wiring the rest, the same call works from your terminal:
curl -X POST \
"https://api.apify.com/v2/acts/native_emblem~shein-product-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"keywords":["summer midi dress"],"maxItems":25}'
One warning: run-sync holds the connection open until the actor finishes, so keep maxItems modest for a tracker. You're pricing a watchlist, not mirroring the catalog. Small inputs come back in a few seconds and never bump the sync timeout.
3. Parse the products
Add a Code node. The dataset comes back as items, and you just pull the fields you care about into a flat shape the next steps can diff. Product ID as the key, price as the value, name for the notification text.
// n8n Code node, runs once over all incoming items
return items.map(({ json }) => ({
json: {
id: json.productId,
name: json.name,
price: json.price, // current price as a number
url: json.url,
},
}));
Field names depend on the actor's output schema, so glance at one real item and map accordingly. The point is you leave this node with one clean record per product: id, name, price, url.
4. Diff against last run
You need somewhere to remember yesterday's price. A Google Sheet is the no-fuss choice and the one I'd start with: one row per product ID, columns for name, last price, and URL. n8n's Google Sheets node reads and writes it directly. A tiny Postgres table or even n8n's own static data works too, but a sheet you can eyeball is the friendliest for a first build.
Read the sheet, join on product ID, and compare. Add another Code node, or an IF node if you prefer clicking to typing:
// keep only products whose price dropped vs the stored value
return items.filter(({ json }) =>
json.lastPrice != null && json.price < json.lastPrice
).map((item) => ({
json: {
...item.json,
drop: item.json.lastPrice - item.json.price,
},
}));
Then write the fresh prices back to the sheet so the next run compares against today. That write-back is the step people forget, and without it every run re-alerts on the same old drop forever.
5. Notify on a drop only
Whatever survives the filter is a genuine price drop, so hand it to a notification node. Slack, Telegram, Discord, email, n8n has a node for all of them. Message body straight from the fields you carried through:
"summer midi dress" dropped 4.20 to 11.79. {url}
If nothing dropped, the filter passes zero items, the notify node does nothing, and you hear nothing. Silence is the correct default for a price tracker. You want it to interrupt you exactly when it matters and stay quiet the other 364 mornings.
That's the whole thing
Five nodes, one scheduled trigger, one API call that both runs the scraper and returns the data, a sheet for memory, and a filter that only speaks up on a drop. Swap keywords for a list of exact product URLs and you're watching a specific watchlist instead of a search. Point it at any of the fields the actor returns, stock status, rating, whatever, and the same skeleton becomes a back-in-stock alert or a review watcher. The pattern outlives the example.
The SHEIN actor I wired here is one I publish on Apify: proxyless and clean-JSON, so parse steps like the one above stay this short. It takes a keyword and returns matching products, so you don't need product URLs to start, and it's priced per product actually returned ($5 per 1,000 search results). It's the same extraction engine behind Cartpie, the e-commerce product-data platform I'm building. Wire it into n8n once and you'll find a dozen more things worth watching.
Top comments (0)