Open-source project
jef/streetmerchant avatar
jef/streetmerchant

jef/streetmerchant: a self-hosted stock checker that never buys for you

🤖 The world's easiest, most powerful stock checker

5,400 stars1,304 forksTypeScriptMIT

At a glance

What is it?
streetmerchant is a TypeScript stock-checking service for people who want to watch store listings around the clock and get notified, not a bot that completes checkout. It installs through npm or Docker, and its dotenv file is where the work of configuring it happens.
Who is it for?
Adopt streetmerchant if you want a self-hosted watcher that notifies you and stops short of buying, and you are comfortable editing a dotenv file. Do not adopt it if you expect an automated checkout bot, because the README states it will not buy for you.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 179 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 3, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What streetmerchant actually watches, and who it is for

streetmerchant is a stock checker. The README puts it plainly: the service will not automatically buy for you. That single sentence defines the audience. It is for people who want to know when an item is available at a store, and who are willing to complete the purchase themselves. It runs continuously, described in the README as running 24/7, 365, looking for the items you want.

The second half of its purpose is notification. The README lists notifications to most platforms and devices, and the dependency list backs that up with packages for Slack, Discord, Telegram, Pushbullet, APNs, MQTT, email via nodemailer, PagerDuty and Philips Hue. That is an unusually wide notification surface for a project of this size, and it is the part most users will actually interact with day to day.

A third piece is the optional dashboard: a web interface with a matrix view of selected stores and series, filter controls, dotenv editing, and restart control. The dashboard is where the project stops being a script and becomes something closer to an appliance. If you only ever want a terminal log, you can skip it; if you want to change which stores are watched without editing files by hand, the dashboard is the reason to set WEB_PORT.

How the checking loop is put together

The repository layout tells you most of the architecture. There is a src/ directory for the TypeScript application, a web/ directory served separately, and a test/ directory with unit tests plus functional tests for notifications and captcha. The package entry point is src/index.ts, and npm run start compiles first (via prestart) and then runs build/src/index.js.

The runtime dependencies show two distinct fetching strategies. cheerio is present, which is the classic HTML parsing route: fetch a page, parse the markup, look for stock indicators. Puppeteer is also present, along with @doridian/puppeteer-page-proxy, which means some store interactions are driven through a real browser rather than a plain HTTP client. That combination is why the Docker image installs Chromium and sets PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser. The browser is not incidental; it is part of how the checker reaches stores that do not expose simple HTML.

State and scheduling are not documented in the README beyond the continuous-checking claim, so treat the loop interval, retry behaviour and per-store concurrency as things you will discover from the configuration and the source rather than from the front page. The dotenv-example file at the repository root is the intended starting point for that configuration, and the README points to jef.buzz/streetmerchant/getting-started for customization.

Installing streetmerchant with npm and running a first check

The README gives a four-part quick start: clone, install, start. Node.js is required, and package.json declares engines.node >=12.0.0. The prestart script compiles the TypeScript before the process runs, so the first start is slower than later ones.

bash
git clone https://github.com/jef/streetmerchant.git
cd streetmerchant && npm i && npm run start

After the clone and install, npm run start triggers the compile and then executes node build/src/index.js. You should expect to see console output from the running checker. Before that first run is useful, copy the dotenv-example file to dotenv and set the stores and series you care about; the README does not spell out those keys, but it does point to the getting-started page for customization.

The web dashboard is opt-in. Set WEB_PORT in dotenv and open http://localhost:<WEB_PORT> while streetmerchant is running. The README describes the dashboard as offering a matrix view of selected stores and series, filter controls, dotenv editing and restart control. If WEB_PORT is unset, you get the notification-driven experience only.

Running streetmerchant in Docker instead

The Docker route exists so you do not have to install Node.js or Chromium yourself. docker-compose.yml defines a single service named streetmerchant, built from the repository Dockerfile or pulled as ghcr.io/jef/streetmerchant:latest, with env_file pointing at dotenv. The Makefile wraps the common operations, with run as the default goal.

bash
make build
make run

make build runs docker-compose build streetmerchant and make run runs docker-compose up. For a background process, make run-detached maps to docker-compose up -d, and make stop maps to docker-compose down. The image is a two-stage build: the builder stage runs npm ci and npm run compile, then npm prune --production, and the final stage adds Chromium and runs as a non-root appuser with DOCKER=true in the environment. If you are deploying this on a small always-on box, that Docker path avoids the most common source of breakage, which is a missing or mismatched browser binary.

What happens when a store fights back

The honest limitation is in the repository structure before it is in the README: there is a functional test target called test:captcha, and the package scripts include both test:captcha and test:notification. A stock checker that needs a captcha test target is a stock checker that expects to meet captchas. Puppeteer and a page proxy library are in the dependency list for the same reason. If a store you care about deploys aggressive bot detection, streetmerchant's browser automation can be blocked, and the README does not document a fallback for that case.

The second limitation is the one the project states itself: it will not buy for you. It can add to cart when available and even open the browser for you, per the README, but checkout is manual. Anyone looking for an end-to-end purchasing bot is looking at the wrong tool, and no amount of configuration changes that.

The third is operational. A checker that runs 24/7 with a browser attached is a long-lived process that consumes memory and needs to be restarted when it wedges. The dashboard's restart control exists precisely because that happens. The README does not document automatic recovery, health checks or alerting on the checker's own failure, so you are responsible for noticing when it stops working.

streetmerchant versus writing your own poller

The realistic alternative is not another product; it is a short script. A cron job that fetches a product page, greps for an in-stock string and posts to a webhook is maybe forty lines and has no build step, no Chromium and no dependency tree. For one store and one item, that is the better engineering choice, and streetmerchant's own breadth works against it there.

The difference in approach is where the effort sits. A custom script puts the complexity in the store: every site you add needs its own parsing logic and its own handling of layout changes. streetmerchant puts that complexity in the project, which is why it carries cheerio for HTML parsing and Puppeteer for browser-driven stores, and why the Dockerfile installs Chromium. You trade a heavier runtime for not maintaining per-store scrapers yourself.

The second difference is notification plumbing. A custom script needs you to write each integration. streetmerchant ships dependencies for Slack, Discord, Telegram, Pushbullet, APNs, MQTT, email, PagerDuty and Hue. If you want stock alerts on your phone and a light to turn on, that is already built. If you want one webhook, it is overhead.

Maintenance, licence and what the release history shows

The repository is not archived, and its last push was on 2026-04-08. The most recent release listed is v3.12.0 from 2025-07-20, preceded by v3.11.0 and v3.10.0 in January 2025. The gap between the last release and the last push suggests commit activity without a tagged release in the intervening period, but the repository does not describe what those commits contain.

Upgrade cost is driven by the runtime, not by the code. The Dockerfile pins node:16.18.0-alpine3.16 in both stages, and package.json requires Node.js 12 or newer. Node 16 is past its end-of-life window, so a self-hosted deployment on that base image inherits whatever that implies for your environment. Moving to a newer Node major means re-checking the dependency set, which includes older pinned packages such as open 8.2.1 and discord.js ^13.0.1.

The licence is MIT, declared in package.json and in the Dockerfile's org.opencontainers.image.licenses label. MIT is permissive, which means you can run, modify and redistribute the code with the licence and copyright notice preserved. What MIT does not do is grant you anything with respect to the stores being checked. Whether automated polling is permitted is a matter of each store's terms, and the repository does not address that. That is a question for your own reading of those terms, not a legal conclusion this article can draw.

Editorial conclusion

Adopt streetmerchant if you want a self-hosted watcher that notifies you and stops short of buying, and you are comfortable editing a dotenv file. Do not adopt it if you expect an automated checkout bot, because the README states it will not buy for you. Before committing, verify that the stores and series you care about are actually covered in the configuration, and decide whether you want the npm route (which requires Node.js 12 or newer) or the Docker route, which installs Chromium and sets PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser.

Frequently asked questions

Does streetmerchant automatically buy items for me?

No. The README states that the service will not automatically buy for you. It can add to cart when available and open the browser for you, but checkout is left to you.

How do I install streetmerchant?

The README quick start clones the repository and runs npm i && npm run start, which requires Node.js. A Docker path also exists: docker-compose.yml builds the service from the repository Dockerfile, and the Makefile exposes make build and make run.

How do I enable the streetmerchant web dashboard?

Set WEB_PORT in dotenv and open http://localhost:<WEB_PORT> while streetmerchant is running. Without WEB_PORT set, the dashboard is not served.

Why does the streetmerchant Docker image include Chromium?

The Dockerfile installs chromium and sets PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser, matching the Puppeteer and page-proxy dependencies in package.json. Some store checks are driven through a real browser rather than plain HTTP fetching.

What licence does streetmerchant use?

MIT, declared in package.json and in the Dockerfile's org.opencontainers.image.licenses label. The repository does not address whether automated polling is permitted by the stores being checked.

Official sources

  1. jef/streetmerchant on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/jef-streetmerchant.svg)](https://hysenlabs.com/projects/jef-streetmerchant)