Skip to main content

Generate Shopify add-to-cart permalinks from a store's public products.json.

Project description

Shopify-ATC

CI

A command-line tool that turns any Shopify storefront into a list of direct add-to-cart permalinks.

Point it at a store and it reads the shop's public catalog, then prints a ready-to-click …/cart/add?id=… link for every product variant — so you can drop an item straight into your cart instead of clicking through the product page. Output comes in human-readable text, JSON, or CSV.

How it works

Shopify exposes two public, documented features this tool builds on:

  • /products.json — every Shopify store publishes its catalog (products, variants, prices, stock) as JSON. No API key required.
  • /cart/add?id=<variant_id> permalinks — Shopify's built-in cart permalink format adds a specific variant to the cart in one request.

Shopify-ATC fetches the first, then generates the second for each variant.

Features

  • Add-to-cart links for every variant — resolves each product's variants and builds a /cart/add permalink with a configurable quantity.
  • In-stock filtering--in-stock-only drops sold-out variants so you only see what you can actually buy.
  • Three output formatstext for reading, json for piping into other tools, csv for spreadsheets.
  • Clear failure modes — a non-Shopify URL, an unreachable host, and an HTTP error each produce a distinct message and a distinct exit code, rather than one catch-all "something went wrong".

Tech Stack

  • Language: Python 3.9+
  • HTTP: requests
  • CLI: argparse (standard library)
  • Tests: pytest (HTTP mocked — the suite runs fully offline)
  • CI: GitHub Actions, matrix across Python 3.9–3.13

Getting Started

Prerequisites

  • Python 3.9 or newer

Installation

# From PyPI (recommended)
pip install shopify-atc

# …or isolated with pipx
pipx install shopify-atc

This installs a shopify-atc command.

Runnable examples (CLI and library) live in examples/.

For local development from a clone:

# Editable install with test deps
pip install -e ".[dev]"

Usage

shopify-atc <store-url> [--limit N] [--in-stock-only] [--quantity N] [--format text|json|csv]
Flag Default Description
store_url Store URL, e.g. https://www.allbirds.com (scheme optional)
--limit 250 Max products to fetch (Shopify's page maximum)
--in-stock-only off Only include available variants
--quantity 1 Quantity placed in each cart link
--format text text, json, or csv

Examples

# Human-readable, in-stock only
shopify-atc https://www.allbirds.com --in-stock-only

# JSON for scripting
shopify-atc https://www.allbirds.com --limit 50 --format json > catalog.json

# CSV for a spreadsheet
shopify-atc https://www.allbirds.com --format csv > catalog.csv

Text output looks like:

Trino® Cozy Crew - Heathered Onyx
https://www.allbirds.com/products/trino-cozy-crew-heathered-onyx
  S (W5-7) — $24.00
  https://www.allbirds.com/cart/add?id=39574630924368&quantity=1

Exit codes: 0 success · 2 bad arguments or unreachable host · 3 HTTP error from the store · 4 not a Shopify storefront.

Use as a Python library

Everything the CLI does is available programmatically. The key names are re-exported from the top-level package:

import shopify_atc

base = shopify_atc.normalize_url("www.allbirds.com")  # -> https://www.allbirds.com

try:
    products = shopify_atc.fetch_products(base, limit=5)
except shopify_atc.ShopifyError as exc:
    raise SystemExit(str(exc))

products = shopify_atc.filter_in_stock(products)  # optional: drop sold-out variants

# Render to any format the CLI supports:
print(shopify_atc.render(products, "json", base, quantity=1))

# …or work with the dataclasses directly:
for product in products:
    for variant in product.variants:
        print(variant.title, variant.price, f"{base}/cart/add?id={variant.id}&quantity=1")

API at a glance

Name Description
fetch_products(url, limit=250, *, timeout=15) Fetch + parse a store's products.json into Product objects. Raises a ShopifyError subclass on failure.
filter_in_stock(products) Return products keeping only available variants; drops products left empty.
normalize_url(url) Trim whitespace/trailing slash and default to https:// if no scheme.
render(products, fmt, base_url, quantity) Render products as "text", "json", or "csv".
Product, Variant Dataclasses describing a product and its variants.
ShopifyError Base exception; subclasses NetworkError (exit 2), HTTPError (exit 3), NotShopifyError (exit 4).

Development

# Install with dev dependencies
pip install -e ".[dev]"

# Run the test suite
pytest

Project Structure

Shopify-ATC/
├── shopify_atc/
│   ├── client.py        # fetch + parse products.json into typed dataclasses; typed errors
│   ├── formatters.py    # pure text / json / csv renderers
│   └── cli.py           # argparse + error→exit-code wiring
├── tests/               # offline tests (HTTP mocked)
├── pyproject.toml       # packaging + `shopify-atc` console entry point
└── .github/workflows/   # CI

Responsible use

Shopify-ATC reads only public endpoints and generates links — it does not log in, store payment details, or complete checkouts. It is not affiliated with Shopify. Respect each store's Terms of Service and avoid hammering a storefront with rapid repeated requests.

License

MIT

Author

Jacob Kanfer — GitHub

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

shopify_atc-1.0.0.tar.gz (13.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

shopify_atc-1.0.0-py3-none-any.whl (9.1 kB view details)

Uploaded Python 3

File details

Details for the file shopify_atc-1.0.0.tar.gz.

File metadata

  • Download URL: shopify_atc-1.0.0.tar.gz
  • Upload date:
  • Size: 13.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for shopify_atc-1.0.0.tar.gz
Algorithm Hash digest
SHA256 7c63112f0213f19f8d6767ea381b56efd6209611e4fbecb39c10213452cb25b7
MD5 a1802ebd8ff4d5c57b70372b8403090c
BLAKE2b-256 edec5d163f80110bab29ffc90a8133295cc6bb675c9e10ba14823900aba5cadb

See more details on using hashes here.

Provenance

The following attestation bundles were made for shopify_atc-1.0.0.tar.gz:

Publisher: publish.yml on Technical-1/Shopify-ATC

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file shopify_atc-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: shopify_atc-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 9.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for shopify_atc-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 878eb013fdde77907c07054a93a8e7620440f186ae1ff985b3a20fe59467ad02
MD5 221b73c2e7fe8c0f86ff6185e0f24004
BLAKE2b-256 6ae8a4a8720231382c036a80b110f88b65499bde50cb024417ccb859342d2f67

See more details on using hashes here.

Provenance

The following attestation bundles were made for shopify_atc-1.0.0-py3-none-any.whl:

Publisher: publish.yml on Technical-1/Shopify-ATC

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page