Check a Meta ad batch for duplicates before upload with Python
A short Python check that flags ads in a batch sharing the same hook and visual before you upload. Useful now that Meta rates creative diversity.

Before you spend on a batch of ads, check that no two of them are the same ad. The script below builds a grid of hooks, visuals and formats, then flags any two ads that share the same hook and the same visual. It is a bookkeeping check, not a model of how Meta scores anything.
The reason to bother is Meta's Creative Diversity Score, rated Low, Medium or High and dated 2026-08-26 by the Common Thread summary (read 2026-10-02). That page gives no formula, so the check only guards against the obvious failure: the same ad uploaded several times under different file names.
Why check before generating, not after?
Each generated clip or image costs money, and Sume reserves the cost when you submit. A duplicate you catch in a spreadsheet costs nothing. Video generation bills at provider list times 1.25 per the docs, so a skipped duplicate is a saved job.
What does the check do?
It treats an ad as a hook, a visual and a format. Two ads clash when hook and visual match, because a different aspect ratio of the same creative is the same idea cropped twice. Run it on the plan, then generate only the rows that pass.
from itertools import product
hooks = ["Free shipping ends Friday", "Why 4,000 people reorder", "Fits in a coat pocket"]
visuals = ["desk flat lay", "outdoor walk", "kitchen counter"]
formats = ["9:16", "1:1", "4:5"]
plan = []
for i, (h, v, f) in enumerate(product(hooks, visuals, formats)):
plan.append({"id": f"ad-{i:02d}", "hook": h, "visual": v, "format": f})
# Keep one format per hook and visual pair for the diversity test.
seen = {}
keep, clash = [], []
for ad in plan:
key = (ad["hook"], ad["visual"])
if key in seen:
clash.append((ad["id"], seen[key]))
else:
seen[key] = ad["id"]
keep.append(ad)
print(len(plan), "planned,", len(keep), "distinct,", len(clash), "same idea")What do I do with the clash list?
Either drop the clashing rows or change the hook or visual so they stop clashing. Crops of the same idea for other placements are a separate need, covered in the post on rendering every ratio.
What does Sume add?
Once the plan is clean, submit each distinct row as its own job with its own Idempotency-Key, for example the id from the plan. A replay with the same key returns the original job instead of creating a second one, per the Sume differences table in the video docs.
Sources
Related posts
More in Developers
- Midjourney collaborative generation: who can see jobs on Sume?
Midjourney plans ways to generate together. On Sume, an API key reads only the jobs its own member created, so sharing takes a plan. Here are the rules.
- Midjourney edit history: keep an edit lineage with Sume job metadata
Midjourney added edit-history navigation and plans persistent edit history. For the Sume image API, build your own lineage with metadata and the jobs list.
- Midjourney Enhance replaces Upscale: the Sume image upscale API
Midjourney's v8.2 editor swapped its Upscale button for Enhance. To upscale from code, Sume has a dedicated image upscale route with factor 1 to 4.
- Midjourney Style Profiles tab: a style library file for Sume
Midjourney added Style Profiles and Featured tabs with detail pages. For the Sume image API, keep a small JSON style library and merge it into each request.
Written by Sume