Skip to main content

Shopify-ATC

CI PyPI Python versions License: MIT

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 formats — text 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. The package is published on PyPI at pypi.org/project/shopify-atc.

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

Release files for shopify-atc 1.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for shopify-atc 1.0.1
File Size Uploaded
shopify_atc-1.0.1.tar.gz 13.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for shopify-atc 1.0.1
File Interpreter ABI Platform
shopify_atc-1.0.1-py3-none-any.whl Python 3 none any Details

Total release size: 22.4 kB

Release files / shopify_atc-1.0.1.tar.gz

Download URL shopify_atc-1.0.1.tar.gz
Size 13.2 kB
Tags Source
SHA-256 checksum
How to use checksums
7f135f56d426d83257295a15532d0ed6384899dca18afb52cc2abc3bab049333
BLAKE2b-256 checksum
How to use checksums
f2560df473fc203293884c3f97275bb80135509576d4e57859f431d3a4697253
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 1, 2026.

Transparency log

Release files / shopify_atc-1.0.1-py3-none-any.whl

Download URL shopify_atc-1.0.1-py3-none-any.whl
Size 9.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
847771e15d8b39bb5638e5e30c56e7b46cc3fe06c555a1617bbe942aa16be4b9
BLAKE2b-256 checksum
How to use checksums
322e61e1225af25c4f14ce3b13a24976d86a1602d5fd1af8bddb1287dea57b5e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 1, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.0.1 This release

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page