Tools

Meta Ads CLI: Setup, Commands and Limits of Meta's Official Ads CLI (2026)

By Chris Pollard
September 23, 202628 min read

The Meta Ads CLI is Meta's official command-line tool for the Marketing API, launched on April 29, 2026 as part of its Ads AI Connectors. It installs as a Python 3.12+ package, authenticates with a system user access token and runs commands in a meta ads <resource> <action> pattern. It covers campaigns, ad sets, ads, creatives, insights, catalogs and datasets, with table, JSON or plain output that scripts can parse. It lets developers and AI coding agents manage Meta ads without writing API code.

Meta is one of the first ad platforms to ship its own command-line tool, and it said plainly who it was for: developers and AI agents. If you've tried to set it up since launch, you've probably found the pieces scattered across eight documentation pages, a launch blog post and a lot of third-party commentary that disagrees on basics like the install path and how authentication works.

This Meta Ads CLI guide pulls it together: the exact install, the system user token setup (where most people stall), every command group, safe use from Claude Code or Codex, current limits, troubleshooting and how it compares with the Ads Uploader CLI. It's checked against Meta's current docs and the latest package, version 1.1.0, and written by a team that builds its own Meta Ads CLI and launches ads through the Marketing API every day.

Why I Think a CLI Is the Better Way to Upload Ads

I've written about this before in our Meta Ads MCP vs CLI comparison, and the crux hasn't changed. In my opinion, a CLI is the better infrastructure for uploading ads.

The first reason is files. A CLI has native control of your file system. Launches usually start from your hard disk, or from cloud storage that's streamed or synced to your computer, and a CLI reads those files de facto. A hosted MCP server, like Meta's at mcp.facebook.com/ads, can't see your disk at all, so files have to arrive by URL, a Drive link or inline data. That workaround is why people find video harder than images through a hosted MCP. Meta's own MCP tool list has a creative tool described as a "single-image link ad creative", plus tools to list existing images and videos, but no dedicated upload tool and no documented file limits. Images look workable; video isn't documented. (A locally installed MCP is different: it runs on your machine and can read files, which is why Ads Uploader's own MCP also comes as a local package that reads from disk.)

The second reason is how the agent finds its way. I find the CLI more deterministic. The command line's feedback works like guardrails: --help output, exit codes and structured errors send the agent down a particular path. With an MCP, the agent needs more knowledge of how the tools fit together to formulate a launch, and many clients load every tool definition into context up front, around 90 of them for Meta's. Some clients now load tools on demand, but an MCP can be more token-heavy, and in my experience the CLI is simply more straightforward.

The MCP still earns its place for conversational reporting and account questions, which our Meta Ads MCP guide covers. This guide stays on the CLI.

What Is the Meta Ads CLI?

In Meta's words, from its Ads CLI documentation: "Ads CLI is a command-line tool for managing Meta advertising from your terminal." It's a Python wrapper over the Marketing API that handles the parts every developer used to rebuild by hand: authentication, pagination, output formatting and error handling.

The key facts, as of September 23, 2026:

  • Package: meta-ads on PyPI, maintained by Meta. The executable is meta.
  • Latest version: 1.1.0, released June 17, 2026.
  • Status: Meta launched the Ads AI Connectors family (the CLI plus the hosted MCP server) as an open beta. PyPI classifies the package as Alpha.
  • License: proprietary. It's free to install but not open source, and there's no public GitHub repo or issue tracker.
  • Audience: Meta names developers building ad integrations, operations teams automating through scripts and CI/CD, and "AI agents and tools".

The motivation for the Meta Ads CLI is familiar to anyone who's automated Meta ads before. One agency buyer on r/FacebookAds described their pre-CLI setup of Python scripts and cron jobs as "brittle as hell", breaking every time Meta changed something in the API. An official tool moves a lot of that maintenance onto Meta, though not all of it.

What the Meta Ads CLI Can Do

The 1.1.0 executable exposes 14 resource groups. The public command reference lists most of them, and the installed package includes a few extras (product feeds, guidance and studies) that the web docs under-document.

ResourceActions
campaignlist, create, get, update, delete
adsetlist, create, get, update, delete
adlist, create, get, update, delete
creativelist, create, get, update, delete
insightsget
cataloglist, create, get, update, delete
product-itemlist, create, get, update, delete
product-setlist, create, get, update, delete
product-feedlist, create, get, update, delete
datasetlist, create, get, connect, disconnect, assign-user
adaccountlist, get, current
pagelist, get
guidancelist
studylist

There's no standalone audience, video, image or lead-form group. Video uploads go through creative create, and custom audiences are referenced inside ad set targeting JSON.

The automation features are what make the Meta Ads CLI agent-friendly:

  • Three output formats: table (the default, for humans), json (for agents and jq) and plain (tab-separated, for awk and cut).
  • --no-input suppresses interactive prompts so a script never hangs waiting for a y/n.
  • Standard exit codes from 0 to 5, so a script or agent can branch on the failure type.
  • Environment variables and .env support, so tokens stay out of command history.

Meta Ads CLI capability map showing campaigns, ad sets, ads, creatives, insights, catalogs, datasets, ad accounts and Pages with their actions

How to Install the Meta Ads CLI

Meta's requirements are short: Python 3.12 or later, and pip or uv.

The official install command is:

pip install meta-ads

Meta's get-started page follows that with a bare uv sync, which only works if you're already inside a uv project with a pyproject.toml. After a normal pip install you don't need it. For a clean, repeatable setup, use a virtual environment and pin the version:

python3.12 -m venv .venv
source .venv/bin/activate
python -m pip install meta-ads==1.1.0
meta --version

Two installation gotchas are worth knowing up front:

  1. "No matching distribution found for meta-ads." The package ships as compiled wheels, not a source distribution. If your Python is older than 3.12, or your platform doesn't match a published wheel, pip can't find it. An r/FacebookAds user hit exactly this in the first week. Check python --version before assuming the package name is wrong.
  2. The API version floats. The CLI doesn't pin a Marketing API version. It inherits whatever the installed facebook-business SDK uses, and a fresh install on September 23, 2026 resolves SDK 26.0.2, which means Marketing API v26.0. Upgrading dependencies can silently change the API version underneath your scripts, so pin both meta-ads and facebook-business for anything you automate.

In Claude Code or Codex, you can ask the agent to install the Meta Ads CLI for you. The part it can't do is the Meta-side setup in the next section.

Authenticating With a System User Access Token

Meta is explicit that the Meta Ads CLI needs a token: "Ads CLI requires a system user access token to authenticate for programmatic access." There's no meta auth login command, no browser OAuth flow and no whoami. You generate a token in Business Manager and give it to the CLI through an environment variable.

This is where most setups stall, so here's the full sequence.

Create the Meta App and System User

  1. In Meta Business Suite, go to Settings > Users > System Users.
  2. Create a system user with the Admin role.
  3. Create or select a Meta developer app for the business.
  4. Add the system user to the app as an App Admin.

A developer app is required for the CLI path. That's a real difference from the hosted MCP, which works through a standard OAuth connector without an app of your own.

Assign Assets and Generate the Token

  1. Assign the system user every asset the CLI will touch: ad accounts, Facebook Pages, datasets (Pixels) and product catalogs if you use them. An unassigned asset is the most common reason meta ads adaccount list comes back empty.
  2. Generate a token for the app with these scopes, which Meta's setup guide lists:
business_management
ads_management
pages_show_list
pages_read_engagement
pages_manage_ads
catalog_management
read_insights

Meta's Postman documentation notes that system user tokens can last up to 60 days or never expire, depending on the option you pick and your business's eligibility.

Five-step Meta Ads CLI authentication flow: admin system user, developer app, asset assignment, scoped token, environment variables

App Permissions and App Review

The Meta Ads CLI always runs through your own Meta developer app, and that app's permissions decide what the CLI can do. When a new job or a different campaign type fails, the cause is often a permission roadblock rather than a CLI bug:

  • Page-backed creative needs pages_manage_ads.
  • Catalogs need catalog_management.
  • Partnership ads need the branded content permissions on top of the ads scopes.
  • Some creative paths are blocked while the app is in development mode, which shows up as error 1885183. A YouTube walkthrough from May showed a campaign and ad set creating fine while the ads failed until the app was switched to Live.

Access level matters too. Meta now describes Marketing API access as Limited or Full. Limited Access is enough for your own business's ad accounts, but managing other businesses' accounts, which is what agencies and partners do, needs Full Access and App Review.

App Review isn't a one-off, either. As Meta's requirements change, you go through it again to keep up. In our experience, reviews that took a couple of days a year ago, before everyone was using AI, now take roughly 10 to 20 days, sometimes longer. Meta doesn't publish a review-time commitment, so request new permissions well ahead of the launch that needs them.

Set Environment Variables and Config Precedence

The CLI reads three variables:

VariablePurposeRequired
ACCESS_TOKENSystem user access tokenYes
AD_ACCOUNT_IDDefault ad account, in act_ formFor most ads commands
BUSINESS_IDDefault business for catalogs and datasetsOptional

Put them in a project .env file that's excluded from version control:

ACCESS_TOKEN=<SYSTEM_USER_TOKEN>
AD_ACCOUNT_ID=act_123456789
BUSINESS_ID=123456789

Settings resolve in this order, highest first: command-line flags, shell environment variables, the project .env, then user config under ~/.config/meta/. Then verify everything works:

meta auth status
meta ads adaccount current
meta ads page list

meta auth status shows whether you're authenticated with a masked token. If adaccount current returns the right act_ ID, you're ready.

Meta Ads CLI Commands: A Working Cheat Sheet

One syntax rule matters before anything else: root options like --output go before ads, and account options go after ads but before the resource.

meta --output json ads campaign list
meta ads --ad-account-id act_123456789 campaign list

Wary of Wiring AI Straight to Meta?

Ads Uploader is loved by power media buyers and agencies, and trusted to launch hundreds of thousands of Meta ads every month.

Try Ads Uploader Free

No credit card required • 7-day free trial

Read Commands (Accounts, Campaigns, Insights)

meta ads adaccount list
meta ads campaign list
meta ads adset list
meta ads ad list
meta ads insights get --date-preset last_7d

Insights defaults to last_30d, returns spend,impressions,clicks,ctr,cpc,reach and caps at 50 rows unless you change it. You can filter to one object and add breakdowns:

meta --output json ads insights get \
  --campaign-id <CAMPAIGN_ID> \
  --date-preset last_7d \
  --fields spend,impressions,clicks,ctr,cpc \
  --breakdown publisher_platform

Filters exist for --campaign-id, --adset-id and --ad-id, and breakdowns include age, gender, country, publisher platform, device platform and platform position.

Build a Campaign End to End

This is Meta's documented sequence. Every create command takes --status, so you choose whether each object starts paused or active. These examples create everything paused and switch it on at the end:

# 1. Campaign (budget in cents: 5000 = $50.00 on a USD account)
meta ads campaign create \
  --name "Spring Test | Traffic" \
  --objective OUTCOME_TRAFFIC \
  --daily-budget 5000 \
  --status PAUSED

# 2. Ad set
meta ads adset create <CAMPAIGN_ID> \
  --name "US | Broad" \
  --optimization-goal LINK_CLICKS \
  --billing-event IMPRESSIONS \
  --targeting-countries US \
  --status PAUSED

# 3. Creative (image or --video ./file.mp4)
meta ads creative create \
  --name "Hero Banner" \
  --page-id <PAGE_ID> \
  --image ./banner.jpg \
  --body "Check out our latest deals!" \
  --title "Shop Now" \
  --link-url https://example.com/sale \
  --call-to-action SHOP_NOW \
  --status PAUSED

# 4. Ad
meta ads ad create <AD_SET_ID> \
  --name "Hero Banner Ad" \
  --creative-id <CREATIVE_ID> \
  --status PAUSED

A few rules the flags won't tell you:

  • Budgets are in the account's minor currency unit. 5000 is $50.00 in USD. Check the account currency before an agent writes a budget.
  • Budget lives in one place. Put it on the campaign (CBO) or on the ad sets (ABO), not both. Both at once usually returns error 1885621.
  • --targeting-countries is the only simple targeting flag. Age, gender, interests, custom audiences, exclusions and manual placements go through --targeting as JSON or @file.json.
  • Dynamic creative needs a dynamic ad set. Create the ad set with --dynamic-creative first.
  • The Instagram flag changed. The web reference says --instagram-actor-id; the 1.1.0 package uses --instagram-user-id. Run meta ads creative create --help on your installed version.

Consistent names matter more when a script or agent is creating objects, because you'll be reading them back in lists later. Settle a naming convention before you automate anything.

Meta Ads CLI build sequence: create the campaign, ad set, creative and ad, review them, then launch each layer

Go Live, Pause and Clean Up

Activation is three separate updates, one per delivery layer:

meta ads campaign update <CAMPAIGN_ID> --status ACTIVE
meta ads adset update <AD_SET_ID> --status ACTIVE
meta ads ad update <AD_ID> --status ACTIVE

Pausing is the same command with --status PAUSED. Deletes prompt for confirmation unless you pass --force, and they cascade: deleting a campaign deletes its ad sets and ads, and deleting an ad set deletes its ads.

meta ads campaign delete <CAMPAIGN_ID>

Catalogs and Datasets

Catalog and dataset commands resolve the business from --business-id, then BUSINESS_ID, then the configured ad account.

meta ads dataset create --name "Website Pixel"
meta ads dataset connect <PIXEL_ID> --ad-account-id act_123456789
meta ads dataset connect <PIXEL_ID> --catalog-id <CATALOG_ID>
meta ads catalog create --name "My Product Catalog"
meta ads product-set list --catalog-id <CATALOG_ID>

Dataset creation needs a business admin to have accepted Meta's Business Tools terms (error 1870092 if not). Datasets are the same Pixels you see in Events Manager, so anything you create here shows up there too.

Does the Meta Ads CLI Create Ads Paused or Active?

Campaigns, ad sets and ads start paused unless you pass --status ACTIVE. Meta's Ads CLI tutorial says: "Ads CLI creates everything in PAUSED status by default." In version 1.1.0, creatives are the exception and default to active. Either way it's your call: set --status on each create, and switch objects on or off afterwards with update.

Running the Meta Ads CLI From Claude Code or Codex

Nothing special is needed to connect an agent. Claude Code, Codex and similar tools run shell commands, so they run the Meta Ads CLI exactly as you would and parse --output json. That's the whole integration.

The important thing to understand is that the agent inherits every permission the token has. The sharpest comment in an early r/FacebookAds thread made this point: the same setup that drafts replacement creatives can also change budgets and pause campaigns, so your review step is the only thing standing between a draft and a live change, and it only works if the agent isn't auto-approving writes. Their recommended split is the one to copy: auto-approve reads, gate anything that mutates spend or status.

In Claude Code, that maps directly onto permission rules in .claude/settings.json:

{
  "permissions": {
    "allow": [
      "Bash(meta --output json ads campaign list:*)",
      "Bash(meta --output json ads insights get:*)",
      "Bash(meta ads adaccount current:*)"
    ],
    "ask": [
      "Bash(meta ads campaign create:*)",
      "Bash(meta ads campaign update:*)",
      "Bash(meta ads adset update:*)",
      "Bash(meta ads ad update:*)"
    ],
    "deny": [
      "Bash(meta ads campaign delete:*)"
    ]
  }
}

Codex has its own approval settings; use them the same way, so reads run freely and writes wait for you.

A few more guardrails that hold up in practice:

  • Use a dedicated system user for the agent, assigned only to the accounts it needs. Don't reuse a broad shared token.
  • Keep the token in .env, never in a prompt, a CLAUDE.md file or a command argument.
  • Ask for a written plan before any build: account ID, parent IDs, objective, budgets in both cents and dollars, targeting, Pixel and final status of every object. Then have the agent read each object back in JSON and compare.
  • Never let the agent use --force on its own. And note that --no-input only suppresses prompts. It isn't a safety feature.
  • Cap loops and retries. A retry loop on a failed create is how you end up with five duplicate campaigns.

The most useful agent workflows are read-side. The same Reddit practitioner runs a morning check that pulls active campaigns, compares spend, ROAS and CPL over the last 72 hours, and flags anything past per-client thresholds (a $5 CPL is great for one account and terrible for another). They reported it saved around 45 minutes a day. Their fatigue rule is also a sensible starting point: frequency rising while CTR falls for three or more days triggers a draft of replacement copy, which a human reviews. And good agents add context a threshold can't, such as holding off on a campaign whose CPL jumped because you scaled its budget two days ago.

Limitations and Known Gaps

The Meta Ads CLI is a strong primitive, but some things it doesn't do yet:

  • No dry run or preview. There's no --dry-run, --preview or --validate-only. Your review step has to be a written plan plus a read-back.
  • No transactions. A build is four separate API calls. If the ad fails after the campaign and ad set succeed, those objects stay behind and you clean them up yourself.
  • No batch command. Bulk work means shell loops, which raise the risk of partial failures, duplicates and rate limits.
  • Advanced features need raw JSON. Carousels, Advantage+ creative controls (--degrees-of-freedom-spec, --asset-feed-spec), placement asset customization and complex targeting all take Marketing API JSON. At that point you need to know the API schema.
  • Insights is narrower than the API. You can filter by campaign, ad set or ad, but there's no explicit --level flag, no async reports and no attribution-window control.
  • No named account profiles. Multi-account work runs through AD_ACCOUNT_ID and --ad-account-id, with no client-a / client-b switcher.
  • Some creative fields can't be edited after creation. Plan to create a replacement creative instead.
  • The docs trail the package. The installed 1.1.0 has more flags and resource groups than the public reference, and there's no public changelog. Early users on Reddit said they figured out some commands by trial and error, and --help on your installed version is still the most reliable reference.

Some early limits have been fixed. Launch-week reports said video uploads weren't possible and insights only worked at campaign level. Current versions support --video on creatives and filters for ad set and ad insights.

Troubleshooting Common Errors

Start with the exit code, which tells you which layer failed:

Exit CodeMeaning
0Success
1General error
2Usage or argument error
3Authentication error
4API error
5Resource not found

In scripts, treat these differently. Retrying a usage error (2) or an auth error (3) never works. Only some API errors (4) are worth retrying.

The Meta errors you're most likely to hit:

SymptomLikely CauseFix
Exit 3, API error 190Token missing, expired or revokedRegenerate the token, run meta auth status
Errors 10, 200 or 294Missing scope or access levelCheck token scopes, app access and asset assignment
adaccount list is emptySystem user not assigned to the accountAssign the ad account in Business Settings
Error 1885183Creative post made by an app in development modeSwitch the app to Live and confirm access level
Error 1885621Budget on campaign and ad setPick CBO or ABO, not both
Error 1870092Business Tools terms not acceptedA business admin accepts the terms
Exit 4 with error 17 or 613Rate limitBack off; don't retry in a tight loop

The Meta Ads CLI has no separate rate-limit allowance. It shares the Marketing API's limits, which Meta documents on its rate limiting page. With Limited Access, the ad account score caps at 60 (a read costs about one point, a write about three) and a block lasts five minutes. Full Access raises the cap to 9,000. Budget changes have their own limit of around four per ad set per hour, which matters if an agent likes to fiddle.

Is the Meta Ads CLI Safe for Your Ad Account?

If you spend time on X or in media-buying communities, you'll have seen the noise: advertisers who connected Meta's AI connectors, or pointed an agent at their account, and then posted that the account was restricted for automation. It's worth taking seriously. It's also worth reading carefully, because every case is different, restrictions rarely have a single cause, and we can't comment on the specifics of any one account.

Meta's official position is what its documentation says. The CLI is a Meta-built tool aimed explicitly at developers and AI agents, and it calls the same Marketing API as every other integration, so the same advertising policies, access levels and rate limits apply. Meta hasn't said the CLI exempts an account from any of them, and it hasn't said using the CLI causes restrictions either.

What an agent changes is the pattern of activity. A media buyer in Ads Manager works at human speed. An agent in a loop can fire dozens of writes in a minute, retry failed calls, re-upload the same media and flip budgets back and forth, and that pattern looks very different from the outside than any single call does. The risks you control are the ones covered earlier: writes to the wrong act_ account, budgets in the wrong unit, runaway retries and leaked tokens. Gate writes, cap loops and respect rate-limit errors, and the CLI behaves like any other well-built integration.

Where the Ads Uploader CLI Fits

Meta's CLI and MCP essentially expose the Marketing API in a friendlier shape for agents to call. That's useful, and it's what Meta set out to build. What a thin, general-purpose layer has probably had less thought put into is everything around the calls: pacing requests under rate limits, the pattern of actions an agent performs on an account over a day, and uploading media safely. Meta's CLI docs don't describe any pacing or retry layer; the tool inherits the Marketing API's limits as they are. Those are the things Ads Uploader has built in, and handles on its own backend.

There's a quieter problem too. Getting campaigns, ad sets and ads into exactly the target and exact setup you want is an underappreciated art. Objective, optimization goal, placements, identity, tracking, naming and creative format all have to line up, and the combinations that work aren't written down in one place. That's the whole purpose of Ads Uploader.

The Ads Uploader CLI is built to be driven by an agent like Claude Code or Codex, and it lets you model new ads on your existing ads: save an ad that's already set up the way you like as a preset (ads presets:save --from-ad), and new launches inherit those settings. Across millions of ads launched, we know which combinations of settings go together and where people hit problems, and that collective knowledge sits inside the workflow rather than in a prompt. Your agent uploads a folder of creatives, runs ads create:preview to check exactly what will be created, then creates the ads, using the same presets and saved builds as the web app. The CLI docs cover the full command set.

Three practical differences show up quickly:

  • Setup. Installing is npm install -g @adsuploader/cli (it needs Node.js 18+), then ads login authenticates in your browser with your Ads Uploader account. There's no developer app and no system user token. Meta's pip install meta-ads is also one line if Python 3.12+ is present; the real rigmarole there is the auth: a developer app, an admin system user, asset assignment and a scoped token.
  • Cloud storage. Creative often lives in Google Drive. ads upload:drive "<shared folder link>" hands a link-shared Drive folder to our infrastructure, which downloads and processes the media server-side, and the hosted Ads Uploader MCP accepts a Drive folder or file link the same way. That's often quicker than moving files around yourself.
  • Saved builds you can open. The web app, the CLI and the MCP share the same build. An agent can assemble a whole campaign through the CLI or MCP and return a build link. Open it in the Ads Uploader uploader and you can change text, ad set configuration and enhancements or add more media, then launch from the web or carry on through the CLI or MCP with the same build. An open uploader tab picks up the agent's edits automatically. In a chat-only workflow you don't really see the intended output until the ads launch, and that matters most on other people's accounts.

Which route makes sense depends on your setup:

  • A simple setup: one ad account, static images in a few sizes, one campaign structure. You can build your own skills on Meta's CLI or MCP to upload exactly how you want, and it's a good way to learn the API.
  • Agencies and partners: many accounts, different campaign setups per client, and the complications that come with each. That's where hand-built skills tend to come unstuck, because every new account adds combinations to handle. Ads Uploader is the safety net there. You outsource the knowledge and the implementation to a workflow that's tried and tested by thousands of media buyers and agencies, at a very affordable price point.

There's also the upkeep. Meta's tooling, permissions and approval rules keep moving: access levels have been renamed to Limited and Full, new campaign types bring new permissions, App Review applies once an app manages other businesses' accounts and has to be repeated as requirements change, and in our experience those reviews now take far longer than they used to. Having someone else keep up with the tooling, permissions and approvals means you're not left behind when they change. Ads Uploader is an approved Meta app, maintained by us, with established channels to raise platform and API issues with Meta when something breaks on Meta's side, so tracking those changes is our job rather than yours.

Meta Ads CLI vs Ads Uploader CLI

Here's how the two compare, side by side:

Meta Ads CLIAds Uploader CLI
Installpip install meta-ads (Python 3.12+)npm install -g @adsuploader/cli (Node.js 18+)
Auth and setupYour own Meta developer app, an admin system user, asset assignment and a scoped tokenads login in the browser with your Ads Uploader account
PreviewNo dry run or preview; review by reading objects backads create:preview shows what will be created before you create it
Cloud importReads local files; cloud storage has to be synced to diskads upload:drive imports a link-shared Google Drive folder server-side
Builds and reviewEach command is a standalone API call, with no saved planSaved builds shared with the web app and MCP; open the build link to review and edit in the UI
Maintenance and app approvalsYou maintain the app, token, access level and any App ReviewApproved Meta app, maintained by us
CostFree; you pay only ad spendPaid plans

If you want to hand a coding agent Meta's API with nothing in between, the official Meta Ads CLI is the obvious starting point, and for a simple setup it's a good one. If you'd rather not build and maintain the preview, launch logic and approvals yourself, that's the job the Ads Uploader CLI does.

Give Your AI Agent a Safety Net

Launch across every client account with an MCP and CLI built for power media buyers and agencies.

Try Ads Uploader Free

No credit card required • 7-day free trial

Frequently Asked Questions

Is the Meta Ads CLI Free?

Yes. Meta charges no separate fee for the CLI. You install the meta-ads package from PyPI at no cost and pay only your normal ad spend. The package is proprietary rather than open source, and you still need a Meta developer app and a system user token.

Is There an Official Facebook Ads CLI?

Yes. Meta's official CLI for Facebook and Instagram ads is the meta-ads Python package, launched April 29, 2026, with commands under meta ads.

Can the Meta Ads CLI Upload Video Ads?

Yes. Pass a local file to meta ads creative create with --video and the CLI uploads it. Meta documents mp4, mov, avi, mkv and wmv files, and dynamic creative accepts up to 10 videos through repeatable --videos flags.

Do I Need to Be a Developer to Use the Meta Ads CLI?

You don't need to write API code, but the setup is developer-flavored: Python 3.12+, a Meta developer app, an admin system user with assigned assets and a token with the right scopes. Many media buyers let an AI coding agent handle the install and run the commands.

Can I Manage Multiple Ad Accounts With the Meta Ads CLI?

Yes, if the system user is assigned to each account. List them with meta ads adaccount list, set a default with AD_ACCOUNT_ID, or override per command with --ad-account-id. There are no named profiles, so name the account explicitly on every write.

What Python Version Does the Meta Ads CLI Need?

Python 3.12 or later. The package ships as compiled wheels, so an older Python or unsupported platform returns "No matching distribution found." A Python 3.12 or 3.13 virtual environment avoids it.

Does the Meta Ads CLI Work With Claude Code and Codex?

Yes. Meta lists AI agents as an intended audience, and any agent that runs shell commands and reads JSON can drive it. Neither agent adds safety on its own, so auto-approve reads and require your approval for creates, activations, budget changes and deletes.

Will Using the Meta Ads CLI Get My Ad Account Banned?

There's no simple yes or no. The CLI is Meta's own tool for developers and AI agents, and Meta hasn't said using it causes restrictions or exempts you from them. Policies, access levels and rate limits apply as they do to any integration. Some advertisers report restrictions after automating with agents, but every case is different, so keep writes gated and loops capped.

What's the Difference Between the Meta Ads CLI and the Meta Ads MCP?

The CLI is a local Python tool that runs shell commands with a system user token. The Meta Ads MCP is a Meta-hosted server at mcp.facebook.com/ads that AI chat clients connect to through OAuth, without a developer app in the standard connector flow. The CLI suits scripts and coding agents; the MCP suits conversational work.

Getting Started With the Meta Ads CLI

The Meta Ads CLI gives developers and AI agents a first-party, scriptable way into the Marketing API, and version 1.1.0 covers far more than the launch-week release. The short version:

  • Install meta-ads in a Python 3.12+ virtual environment and pin it along with facebook-business.
  • Authenticate with an admin system user token, assigned only to the assets you need, stored in .env.
  • Decide what to build: a single-account, simple setup is easy to script yourself; multi-account agency work is where a maintained launch workflow earns its keep.
  • Plan around the gaps: no dry run, no transactions, no batch command, raw JSON for advanced formats.
  • With an agent, auto-approve reads and gate every write.

Make your first week with the Meta Ads CLI read-only. Pull insights as JSON, then build one test campaign and walk it through review and activation by hand. Once that loop feels routine, you'll know which parts to automate and which to keep in your own hands.

Chris Pollard
Chris Pollard

Chris is the founder of Ads Uploader, helping marketing teams and agencies save hours on Meta Ads automation. After years of watching teams waste time on repetitive ad uploads, he built the tool he wished existed.

Stop Uploading Ads
One by One

Upload hundreds of ads in minutes. Auto-match video aspect ratios and thumbnails. Direct publish to Meta.

Try Ads Uploader Free

No credit card required
7-day free trial

Ad Library Helper

Free Chrome extension to search, filter, and save ads from the Meta Ad Library.

Get It Free

Built by Ads Uploader

Ready to Scale Your Meta Ads?

See why performance marketers, agencies and brands trust Ads Uploader to handle their bulk creative uploads. Launch hundreds of ads in minutes, not hours.

Get Started Free

Free 7-day trial

No credit card required

Cancel anytime