Agent-optimized CLI for the Pexels API.
Hard fork of agynio/pexels-cli.
Install
- Build from source:
cargo install --path pexels
Auth
- Env:
PEXELS_TOKEN(orPEXELS_API_KEY); fallback order:PEXELS_TOKEN→PEXELS_API_KEY. - Config file:
~/.config/pexels/config.yaml(or OS equivalent). Runpexels auth login: it readsPEXELS_TOKEN/PEXELS_API_KEYif set, otherwise prompts (or reads stdin, e.g.echo "$KEY" | pexels auth login). The key is never accepted as a CLI argument.
Usage examples
pexels auth statuspexels photos search -q catspexels photos curatedpexels videos popularpexels collections featured
Downloads
-
pexels photos download <id> <path>savessrc.original. Add--sizeonphotos search/photos urlto pick anothersrc.*variant (original,large2x,large,medium,small,portrait,landscape,tiny). -
pexels videos download <id> -o <path>inspectsvideo_filesand downloads the best match. Filters:--quality(sd/hd/uhd),--orientation(landscape/portrait/square, derived from width vs height),--max-width <px>,--prefer <substring>(matched againstfile_type, defaultmp4so HLS playlists aren't picked by accident). -
Both downloads stream straight to a
<path>.partfile, fsync, then atomically rename into place — a dropped connection never leaves a truncated file at<path>. -
Pass
-as the id to read the resource's JSON from stdin instead of fetching it from the API — saves the metadata request when you already have the object (e.g. from a priorsearch --raw):pexels videos search "cats" --raw | jq -c '.videos[0]' | pexels videos download - -o cat.mp4
-
photos search/videos searchaccept--download <dir>to save every result in one command (same filters as above), using only the one API request the search itself made:pexels videos search "cats" --download ./out --max-width 1280. Per-item failures are collected in the output instead of aborting the batch. (get --downloaddoesn't exist: for a single id that's exactly whatdownload <id>already does.) -
--timeout(default 15s) governs JSON API calls;--download-timeout(default 120s) governs asset downloads only, since large video files need longer than a metadata call.
Pagination
--all(with--limit/--max-pages) fetches multiple pages by re-issuing the request with an incrementedpage, not by following thenext_pageURL the API returns — that URL has shipped malformed (a duplicated/v1/segment) on both photos and videos search.
Output
- Successful outputs are wrapped as
{ data: <payload> }for single-resource outputs, and{ data: <items[]>, meta: { total_results?, next_page?, prev_page?, request_id? } }for list endpoints. - For list endpoints,
datais the items array (photos/videos/collections/media). For single-resource endpoints,datais the object andmetais omitted. page/per_pageare omitted.next_page/prev_pageare integers (page numbers) or null.- Field selection via
--fieldssupports dot paths and sets:@ids,@urls,@files,@thumbnails,@all. - Some fields are omitted by default for lighter responses; include heavy fields via
--fields.
Testing
- Unit tests cover projection, config precedence, error mapping, and page parsing.
- Live tests run in CI when
PEXELS_TOKENis present and event is safe. Commands:pexels auth statuspexels photos search -q catspexels photos curatedpexels videos popularpexels collections featured
CI/Release
- CI runs: lint -> unit tests -> build -> live tests (guarded by
secrets.PEXELS_TOKENand internal PRs/main). - On push to main, a release tag is created and binaries for Linux/macOS/Windows are uploaded.