Skip to content

Instantly share code, notes, and snippets.

@snacsnoc
Created May 24, 2025 16:19
Show Gist options
  • Select an option

  • Save snacsnoc/6f474cbdb6060434fb31ceeab646a305 to your computer and use it in GitHub Desktop.

Select an option

Save snacsnoc/6f474cbdb6060434fb31ceeab646a305 to your computer and use it in GitHub Desktop.
Dollar General coupon loader via API
#!/usr/bin/env python3
"""
Dollar General – clip **everything** that is currently visible in
‘Digital Coupons’.
USAGE
DG_COOKIE="Paste the long Cookie header here" \
python3 dg_clip_all.py
"""
import json, os, sys, time, urllib.parse, requests
BASE = "https://www.dollargeneral.com/bin/omni/coupons"
HEAD = {
"User-Agent": "Mozilla/5.0",
"Accept": "application/json, text/javascript, */*; q=0.01",
"X-Requested-With": "XMLHttpRequest",
"Referer": "https://www.dollargeneral.com/deals/coupons",
"Cookie": (
"form_key=6MzGRJsdB2ZZXMXA; " # probably need this
"c_uuid=2501015138020100101138051050168030; " # probably need this
"authType=1; "
"userPreferences=false|false|true; "
),
}
DEVICE_ID = "YOUR-DEVICE-ID" # fixed
STORE_NUM = "25558" # any valid store
PARAMS = {
"searchText": "",
"sortOrder": "2",
"sortBy": "0",
"numPageRecords": "40", # grab many at once
"pageIndex": "0",
"offerSourceType": "1",
"mixMode": "0",
"deviceId": DEVICE_ID,
"isMobileDevice": "false",
"clientOriginStoreNumber": "",
}
print("Starting.....")
sess = requests.Session()
sess.headers.update(HEAD)
def all_offer_ids():
ids, idx = [], 0
while True:
PARAMS["pageIndex"] = str(idx)
r = sess.get(f"{BASE}/search", params=PARAMS, timeout=10)
r.raise_for_status()
data = r.json()
coupons = data.get("Coupons", [])
if not coupons:
break
ids.extend(c["OfferID"] for c in coupons)
idx += 1
print(f"Going thru ID {idx}")
return ids
def activate_batch(offer_ids):
payload = {
"offerGuids": ",".join(offer_ids),
"storeNumber": STORE_NUM,
"deviceId": DEVICE_ID,
"isMobileDevice": "false",
"clientOriginStoreNumber": "",
}
r = sess.post(
f"{BASE}/activate",
data=urllib.parse.urlencode(payload),
headers={"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"},
)
r.raise_for_status()
return r.json()
if not HEAD["Cookie"]:
sys.exit("Set DG_COOKIE env var first.")
offers = all_offer_ids()
print(f"Found {len(offers)} coupons.")
CHUNK = 30 # DG API allows ~50 ids at once, stay safe
for i in range(0, len(offers), CHUNK):
chunk = offers[i : i + CHUNK]
resp = activate_batch(chunk)
ok = sum(1 for o in resp["result"] if o["Success"])
print(f" clipped {ok}/{len(chunk)} (batch {i//CHUNK+1})")
time.sleep(0.4) # be nice
print("Done.")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment