pin-dl 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,326 @@
1
+ # pin-dl
2
+
3
+ Pinterest media downloader CLI.
4
+
5
+ ✨ Inspired by [pinterest-dl](https://github.com/sean1832/pinterest-dl).
6
+
7
+ ## Requirements
8
+
9
+ - Node.js >= 24
10
+ - ffmpeg (optional, required for HLS video remuxing)
11
+
12
+ ## Installation
13
+
14
+ ```sh
15
+ pnpm i -g pin-dl # or npm i -g pin-dl
16
+ ```
17
+
18
+ ## Quick Start
19
+
20
+ ```sh
21
+ # Download a board — bare URL, no subcommand needed
22
+ pin-dl https://www.pinterest.com/user/board-name/ -o ./output
23
+
24
+ # Search — bare query, no subcommand needed
25
+ pin-dl "dark academia interiors" -o ./refs -n 200
26
+ # Words without quotes also work:
27
+ pin-dl dark academia interiors -o ./refs -n 200
28
+
29
+ # Log in for private boards
30
+ pin-dl login
31
+
32
+ # Download a board section
33
+ pin-dl https://www.pinterest.com/user/board/ --section "Kitchen Ideas" -o ./kitchen
34
+
35
+ # Resume an interrupted download
36
+ pin-dl download board.json -o ./output --resume
37
+ ```
38
+
39
+ ---
40
+
41
+ ## Commands
42
+
43
+ ### `login`
44
+
45
+ Opens a browser to log in to Pinterest and saves session cookies for use with private boards.
46
+
47
+ ```
48
+ pin-dl login [options]
49
+ ```
50
+
51
+ | Option | Alias | Default | Description |
52
+ | ---------------------- | ----- | -------------- | ---------------------------------------------------------------------------------------------------------------- |
53
+ | `--output` | `-o` | `cookies.json` | Path to save the cookies file |
54
+ | `--client` | | `chromium` | Browser engine: `chromium` \| `firefox` \| `webkit` |
55
+ | `--browser-executable` | | | Path to a custom browser binary (skips Playwright install check). Also reads `pin-dl_BROWSER_EXECUTABLE` env var. |
56
+ | `--headful` | | false | Show the browser window |
57
+ | `--incognito` | | false | Use an isolated browser context |
58
+ | `--wait` | | `10` | Seconds to wait after login for cookies to settle |
59
+ | `--verbose` | | false | Enable verbose output |
60
+
61
+ The browser binary is downloaded automatically on first use if not found (requires confirmation). To install manually:
62
+
63
+ ```sh
64
+ npx playwright install chromium
65
+ ```
66
+
67
+ **Example:**
68
+
69
+ ```sh
70
+ pin-dl login -o cookies.json --headful --wait 20
71
+ # On success, prints the next step:
72
+ # Use: pin-dl scrape <url> -o ./output --cookies cookies.json
73
+ ```
74
+
75
+ ---
76
+
77
+ ### `scrape`
78
+
79
+ Scrapes images (and optionally videos) from Pinterest board, section, or pin URLs.
80
+
81
+ ```
82
+ pin-dl <url>... # bare URL shortcut — no subcommand needed
83
+ pin-dl get <url>... # alias for scrape
84
+ pin-dl similar <url> # alias for scrape --related
85
+ pin-dl scrape <url>... [options]
86
+ pin-dl scrape --file urls.txt [options]
87
+ ```
88
+
89
+ > **Shortcuts:** Bare URLs and `get` both dispatch to `scrape`. `similar` dispatches to `scrape --related`.
90
+
91
+ | Option | Alias | Default | Description |
92
+ | ------------------ | ----- | ------- | ------------------------------------------------------------------------- |
93
+ | `--output` | `-o` | | Output directory for downloaded files. If omitted, prints JSON to stdout. |
94
+ | `--file` | `-f` | | File containing URLs, one per line. Use `-` for stdin. |
95
+ | `--stdin` | | false | Read URLs from stdin (alias for `--file -`) |
96
+ | `--cookies` | `-c` | | Path to cookies JSON for private boards |
97
+ | `--limit` | `-n` | `100` | Maximum number of items to scrape |
98
+ | `--min-res` | `-r` | | Minimum resolution filter, e.g. `512x512` — skips smaller images |
99
+ | `--section` | | | Board section to scrape by name, e.g. `--section "Kitchen Ideas"` |
100
+ | `--related` | | false | For pin URLs: scrape related/similar pins instead |
101
+ | `--video` | | false | Download video streams if available |
102
+ | `--skip-remux` | | false | Skip ffmpeg remux; output raw `.ts` file |
103
+ | `--reencode` | | false | Force re-encode HLS to MP4 (slower; overrides `--skip-remux`) |
104
+ | `--timeout` | | `10` | Request timeout in seconds |
105
+ | `--delay` | | `0.2` | Delay between requests in seconds |
106
+ | `--save-urls` | | | Save scraped URLs to a JSON file for later use with `pin-dl download` |
107
+ | `--filename` | | `{id}` | Filename template. Variables: `{id}`, `{alt}`, `{index}`. See below. |
108
+ | `--dry-run` | | false | Print found URLs to stdout without downloading anything |
109
+ | `--skip-existing` | `--resume`, `--continue` | false | Skip files that already exist in the output directory |
110
+ | `--caption` | | `none` | Caption format: `txt` \| `json` \| `metadata` \| `none` |
111
+ | `--ensure-cap` | | false | Only include items that have alt text |
112
+ | `--cap-from-title` | | false | Use image title as caption instead of `auto_alt_text` |
113
+ | `--verbose` | | false | Print each downloaded URL |
114
+ | `--dump` | | | Save raw API request/response pairs to a directory for debugging |
115
+ | `--log-file` | | | Append all log output to this file |
116
+
117
+ **Examples:**
118
+
119
+ ```sh
120
+ # Bare URL — no subcommand needed
121
+ pin-dl https://www.pinterest.com/user/board-name/ -o ./output --limit 200
122
+
123
+ # Download a specific board section
124
+ pin-dl https://www.pinterest.com/user/home-ideas/ --section "Kitchen" -o ./kitchen
125
+
126
+ # Find similar pins (alias: pin-dl similar <url>)
127
+ pin-dl https://www.pinterest.com/pin/123456789/ --related -n 50 -o ./similar
128
+
129
+ # Batch from a file; read from stdin
130
+ pin-dl scrape --file urls.txt -o ./output -c cookies.json
131
+ cat urls.txt | pin-dl --stdin -o ./output
132
+
133
+ # Save scraped URLs for later download (no download yet)
134
+ pin-dl https://www.pinterest.com/user/board/ --save-urls board.json
135
+
136
+ # Filter by minimum resolution
137
+ pin-dl scrape <url> -o ./output --min-res 1024x768
138
+
139
+ # Dry run — inspect URLs without downloading
140
+ pin-dl https://www.pinterest.com/user/board/ --dry-run
141
+
142
+ # Resume after interruption
143
+ pin-dl scrape <url> -o ./output --resume
144
+
145
+ # Download videos
146
+ pin-dl scrape <url> -o ./output --video
147
+ ```
148
+
149
+ ---
150
+
151
+ ### `search`
152
+
153
+ Searches Pinterest for a keyword and downloads results.
154
+
155
+ ```
156
+ pin-dl "query" # bare query shortcut — no subcommand needed
157
+ pin-dl dark academia interiors # unquoted words are joined into one query
158
+ pin-dl search <query>... [options]
159
+ pin-dl search --file queries.txt [options]
160
+ ```
161
+
162
+ > **Shortcut:** A bare string (no `https://`, no subcommand) automatically dispatches to `search`. Multiple unquoted words are joined into a single query.
163
+
164
+ Accepts the same options as `scrape` (see table above).
165
+
166
+ **Examples:**
167
+
168
+ ```sh
169
+ # Bare query — no subcommand needed
170
+ pin-dl "minimalist interior" -o ./output -n 50
171
+
172
+ # Multiple queries processed sequentially
173
+ pin-dl search "cats" "dogs" -o ./output
174
+
175
+ # Search from a file of queries
176
+ pin-dl search --file queries.txt -o ./output --save-urls results.json
177
+ ```
178
+
179
+ ---
180
+
181
+ ### `download`
182
+
183
+ Downloads media from a previously saved `--save-urls` file.
184
+
185
+ ```
186
+ pin-dl download <cache.json> [options]
187
+ ```
188
+
189
+ > Passing a URL instead of a cache file prints a helpful error pointing to the correct command.
190
+
191
+ | Option | Alias | Default | Description |
192
+ | ----------------- | ----- | -------------------------- | -------------------------------------------------------- |
193
+ | `--output` | `-o` | filename without extension | Output directory |
194
+ | `--min-res` | `-r` | | Minimum resolution filter, e.g. `512x512` |
195
+ | `--filename` | | `{id}` | Filename template. Variables: `{id}`, `{alt}`, `{index}` |
196
+ | `--video` | | false | Download video streams if available |
197
+ | `--skip-remux` | | false | Skip ffmpeg remux; output raw `.ts` file |
198
+ | `--reencode` | | false | Force re-encode HLS to MP4 |
199
+ | `--skip-existing` | `--resume`, `--continue` | false | Skip files that already exist in the output directory |
200
+ | `--caption` | | `none` | Caption format: `txt` \| `json` \| `metadata` \| `none` |
201
+ | `--ensure-cap` | | false | Only download items that have alt text |
202
+ | `--verbose` | | false | Print each downloaded file path |
203
+ | `--log-file` | | | Append all log output to this file |
204
+
205
+ **Examples:**
206
+
207
+ ```sh
208
+ # Download from a saved URL list
209
+ pin-dl download board.json -o ./output
210
+
211
+ # Resume an interrupted download
212
+ pin-dl download board.json -o ./output --resume
213
+
214
+ # Download only captioned items
215
+ pin-dl download board.json -o ./output --ensure-cap --caption txt
216
+ ```
217
+
218
+ ---
219
+
220
+ ## Workflow: Private Boards
221
+
222
+ ```sh
223
+ # 1. Log in and save cookies
224
+ pin-dl login -o cookies.json
225
+
226
+ # 2. Scrape a private board using the cookies
227
+ pin-dl scrape https://www.pinterest.com/user/private-board/ -o ./output -c cookies.json
228
+ ```
229
+
230
+ ---
231
+
232
+ ## Resuming Interrupted Downloads
233
+
234
+ When you run `pin-dl scrape <url> -o <dir>`, scraped URLs are automatically saved to `<dir>.json` alongside the download. If the download is interrupted:
235
+
236
+ ```sh
237
+ # Option 1: resume from the auto-saved URL list
238
+ pin-dl download ./output.json -o ./output --resume
239
+
240
+ # Option 2: re-run the scrape with --resume (re-fetches URLs, skips existing files)
241
+ pin-dl scrape <url> -o ./output --resume
242
+ ```
243
+
244
+ If you used `--save-urls` explicitly, that file takes precedence over the auto-save.
245
+
246
+ > **Ctrl+C hint:** pin-dl prints the exact resume command when interrupted.
247
+
248
+ ---
249
+
250
+ ## Output File Naming
251
+
252
+ By default, files are named by their Pinterest pin ID:
253
+
254
+ - Images: `<pin_id>.jpg` (or `.png`, etc. based on source)
255
+ - Videos: `<pin_id>.mp4` (or `<pin_id>.ts` if ffmpeg is missing)
256
+ - Captions: same base name — e.g. `<pin_id>.txt` or `<pin_id>.json`
257
+
258
+ Use `--filename` to customise the naming pattern:
259
+
260
+ | Variable | Value |
261
+ | ----------- | ---------------------------------------------------------- |
262
+ | `{id}` | Pinterest pin ID (default) |
263
+ | `{alt}` | Sanitized alt text (spaces → `_`, special chars stripped). Falls back to `{id}` if empty. |
264
+ | `{index}` | 1-based position in the batch |
265
+
266
+ ```sh
267
+ # Sequential numbering
268
+ pin-dl <url> -o ./output --filename "{index}-{id}"
269
+ # → 1-123456.jpg, 2-789012.jpg, ...
270
+
271
+ # Name by alt text
272
+ pin-dl <url> -o ./output --filename "{alt}"
273
+ # → dark_moody_aesthetic.jpg, minimalist_desk_setup.jpg, ...
274
+ ```
275
+
276
+ ---
277
+
278
+ ## Captions
279
+
280
+ The `--caption` option writes metadata alongside each downloaded file:
281
+
282
+ | Mode | Output |
283
+ | ---------- | -------------------------------------------------------------- |
284
+ | `txt` | `<filename>.txt` containing alt text |
285
+ | `json` | `<filename>.json` containing `{src, alt, origin}` |
286
+ | `metadata` | Attempts to embed EXIF metadata (shows warning if unsupported) |
287
+ | `none` | No caption files (default) |
288
+
289
+ Use `--cap-from-title` to prefer the pin title over `auto_alt_text`.
290
+ Use `--ensure-cap` to skip items that have no caption text.
291
+
292
+ ---
293
+
294
+ ## Videos
295
+
296
+ Pinterest pins may include HLS (`.m3u8`) video streams. Pass `--video` to download them.
297
+
298
+ - By default, streams are remuxed to `.mp4` using ffmpeg (must be in `PATH`).
299
+ - Use `--skip-remux` to save the raw `.ts` segment file instead.
300
+ - Use `--reencode` to force a full re-encode to MP4 (slower, maximum compatibility).
301
+
302
+ ---
303
+
304
+ ## Caching / Two-Step Workflow
305
+
306
+ Save scraped media metadata to a JSON file with `--save-urls`, then download later:
307
+
308
+ ```sh
309
+ pin-dl <url> --save-urls board.json # scrape only, save URLs
310
+ pin-dl download board.json -o ./output # download from saved list
311
+ pin-dl download board.json -o ./output --resume # resume if interrupted
312
+ ```
313
+
314
+ This is useful for inspecting results before downloading, or deferring large downloads.
315
+
316
+ ---
317
+
318
+ ## Building from Source
319
+
320
+ After cloning the repository, run:
321
+
322
+ ```sh
323
+ pnpm install
324
+ vp run build # outputs to dist/
325
+ node dist/index.mjs # run directly
326
+ ```
@@ -0,0 +1,2 @@
1
+
2
+ export { };