Bulk product uploader for web admin panels, built with Node.js + Puppeteer. Reads product images and/or a CSV, fills the admin form for each product, uploads the image and saves — with dry-run mode, retries, and upload history.
Posting hundreds of products one by one through a web admin page means filling the same form, picking the same file dialog and clicking the same Save button over and over. This tool started as a Chrome extension and was ported to a terminal CLI so a whole folder of products can be uploaded in one run — processing 300+ items per day and cutting manual work by about 60%.
- Two input sources — scan an image folder (
CODE PRICE.png) and/or import a CSV; rows are merged with images by product code - Vietnamese price shorthand —
500k,1m5,2.5m,1tr2and short numbers (120→120000) are converted automatically - Dry-run mode — fills every form but never clicks Save, so you can verify a batch safely
- Retries — each product is retried up to 3 times before being marked as failed
- Configurable — delay, per-run limit, headless mode, data template (
{maSP} | {note}) via.env - Upload history — every session (success/failure per product, duration) is logged to
upload_history.json - Clean stop —
Ctrl+Ccloses the browser gracefully - Demo included — a mock admin page lets you try the full flow locally
git clone https://github.com/dlam17/auto-upload-cli.git
cd auto-upload-cli
npm install
cp .env.example .env # defaults point at the bundled demo
npm run demo # dry run against examples/mock-admin.htmlSet DRY_RUN=false in .env to actually click Save on the demo page.
Images — one file per product, named CODE PRICE:
images/
SP001 120000.png
SP002 1m5.png → 1,500,000
SP003 2.5m.png → 2,500,000
CSV — header names are detected flexibly (masp/code/id, gia/price, note); , ; | and tab separators are all accepted:
masp,gia,note
SP001,120,Starter pack
SP002,1m5,Limited edition| Input | Result |
|---|---|
120 |
120000 |
500k |
500000 |
1m5 |
1500000 |
2.5m |
2500000 |
1tr2 |
1200000 |
120000 |
120000 |
| Variable | Description | Default |
|---|---|---|
ADMIN_URL |
Admin page with the add-product form | — |
IMAGES_DIR |
Folder of product images | ./images |
CSV_FILE |
Optional CSV file | — |
NOTE |
Default note for all products | — |
DATA_TEMPLATE |
Template for the data field | {maSP} | {note} |
DELAY |
Seconds to wait before saving each product | 0 |
LIMIT |
Max products per run (0 = all) |
0 |
DRY_RUN |
Fill forms without saving | false |
HEADLESS |
Hide the browser window | false |
AUTO_FORMAT_PRICE |
Convert price shorthand | true |
CHROME_PATH |
Use an existing Chrome/Chromium binary | bundled Chromium |
Run with --yes to skip the confirmation prompt.
All form selectors live in one place — SELECTORS in uploader.js. Point them at your admin page's inputs and buttons.
auto-upload-cli/
├── index.js # CLI entry: config, product loading, upload loop, summary
├── uploader.js # Puppeteer automation: open form, fill, upload image, save, retry
├── utils.js # Price parsing, file/CSV parsing, merge, template, history, logger
├── test/utils.test.js # Unit tests (node:test)
├── examples/
│ ├── mock-admin.html # Local demo admin page
│ ├── products.csv
│ └── images/
└── .env.example
npm testMIT © Do Duc Lam
