use at your own risk. This was created late at night by a vibe coder.
Run Meta Ads from code instead of clicking through Ads Manager. Pull analytics, edit ads, and publish campaigns from a script or an agent.
A small Python client over the Meta Marketing API. From a script (or an agent) you can:
- pull analytics: spend, ROAS, clicks and the rest, at account / campaign / ad set / ad level
- edit existing ads: budgets, pause or activate, swap creative, change targeting
- publish new campaigns, ad sets, and ads, plus upload image and video creative
It's all one Graph API; reads and writes are just different endpoints on it. Reads are offline-safe (no token gives you empty results instead of a crash), and every write is dry-run by default: the client builds the real payload, prints what it would send, and changes nothing until you set SAFE_MODE=false and pass apply=True.
pip install -r requirements.txt
python -m headless_ads.demo # builds real payloads, runs them dry, touches nothingIt's intentionally small and blunt. A few things worth knowing before you point it at a real account:
-
Dry-run is the default, which is correct but can fool you: a script can finish clean and still have changed nothing live. A real write needs both
SAFE_MODE=falseandapply=True, and you should confirm the result in Ads Manager afterward. -
A failed read looks like an empty one. Reads return
[]or{}when credentials are missing, by design, but some API errors also come back empty after logging to stderr. If a read returns nothing unexpectedly, check stderr or runpython -m headless_ads.demo --check. -
Config is read once, at import. Set
META_ACCESS_TOKEN,META_AD_ACCOUNT_ID, andSAFE_MODEbefore you start Python. Change them inside a running process and the client won't notice, so start a fresh process instead. -
Uploads are basic. The image and video helpers handle the common path, not a full creative-asset manager. Stick to normal JPEG/MP4 inputs and check the Meta response before wiring an asset into an ad.
-
Your token is full account access. Treat
.envlike a private key. The guard stops this package from writing by accident; it does nothing for a token that's already leaked.
MIT.