Goodbye Microstock CSV Rejections: Automating Title Casing and Keyword Ordering in Practice

Microstock batch upload failures mostly stem from CSV headers and keyword ordering; encoding the rules into pure standard-library scripts solves it.
The article tells how a developer had 60 vector files all rejected within a minute, found the issue was CSV headers rather than the files, and wrote make_metadata.py to encode platform rules. The script outputs exact headers (Adobe Stock 5 columns, Vecteezy 4, Dreamstime 15); applies ~15 lines of Python title-casing rules covering 90% of cases with the rest overridden via titles.json; orders keywords by importance, with the first 10 being specific searchable nouns and long-tail terms after, while removing mismatches. An upload_tracker.py plain-text ledger prevents duplicate uploads. All scripts use only the standard library and run on 1 vCPU/2 GB RAM. The author argues this approach of encoding platform validation rules into scripts also benefits AI content creators' batch submission pipelines.
Uploading 60 vector files and having them all rejected within a minute. The problem wasn't the files themselves, but the CSV headers. This is a pitfall many microstock contributors have fallen into. One developer wrote make_metadata.py to bake the rules for title casing and keyword ordering into a script. This article breaks down its core logic and analyzes what it means for AI content creators' pipelines.
Wrong Headers, All for Nothing
Every microstock platform has a fixed CSV column layout, and the script must output exactly what the platform requires:
- Adobe Stock: 5 columns — Filename, Title, Keywords, Category, Releases.
- Vecteezy: 4 columns — Filename, Title, Keywords, Category.
- Dreamstime: 15 columns — more fields, but the same principle.
Platforms validate the header before reading any data. If the column order is wrong, the submission is rejected instantly no matter how good the titles are — there's no partial acceptance. The author recommends ensuring the header is byte-for-byte correct before worrying about keywords, testing with a single file first, then processing in batches.

Microstock platforms are stock media marketplaces characterized by low prices and high download volumes, such as Shutterstock, Adobe Stock, Vecteezy, and Dreamstime. Contributors upload vectors, photos, videos, and other assets; after platform review, assets gain exposure through search and earn download royalties. For batch submissions, platforms typically require a CSV file with metadata (title, keywords, category, etc.) for automated ingestion. Header validation is the platform's very first validation step: the system parses the CSV's column names and order, confirms an exact match with the defined schema, and only then reads the content row by row. Misspelled column names, incorrect casing, or a deviation in column order will cause the parser to deem the file invalid outright, returning an error for the whole batch without ever reaching human or machine content review.
Title Casing Without Third-Party Libraries
If no titles file is provided, the script falls back to using the filename, converted according to title casing rules. Sounds simple, but there are many edge cases. For example, sticker-pack-cute-cat becomes "Sticker Pack Cute Cat" — that's fine; but svg-icon-for-halloween becomes "Svg Icon For Halloween", where "Svg" should be "SVG" and "for" should stay lowercase in a natural title.
The rules the author established, applied in order:
- Split on hyphens and underscores, since those are the only separators used in filenames.
- Capitalize the first and last words no matter what.
- Keep short connecting words in the middle lowercase: for, and, with, of, the, a, on, in.
- Force-capitalize a small whitelist of initialisms: SVG, PNG, AI, EPS, JPG, PDF, USA, DIY.
- Leave words already in mixed case (like iPhone) untouched — never force-capitalize them.
These rules are about 15 lines of Python with no third-party packages, solving roughly 90% of the author's title problems. The remaining 10% are fixed via a manually maintained titles.json file. The script supports a --titles titles.json argument, prioritizing manual titles, with the fallback rules applying only to batches not yet processed.
Keywords Must Be Ordered, Not Randomly Piled
Keyword order directly affects search ranking. On Adobe Stock, the first 10 keywords carry more search weight than the rest. Most contributors pile on 30 to 50 keywords at random, wasting the one ranking lever they fully control.
The author's keyword rules are mechanical and simple:
- The first keyword is the most important noun. For a cat sticker, that's "cat", not "cute".
- Keywords 2 through 10 are specific, searchable terms — what buyers actually type, such as "cat sticker", "kitten", "pet" — ordered by descending likelihood of buyer search.
- Keyword 11 onward are long-tail terms: style, mood, use case, such as "cute", "kawaii", "printable", "sublimation".
At the same time, remove any keywords that don't match the image. Keyword stuffing triggers account reviews, and rejected batches must be resubmitted. Ten real, well-ordered keywords beat fifty scattered ones.
The pipeline writes keywords into the Keywords column as a comma-separated list in order, with data coming from the same source as titles — titles.json. One file holds the title and keywords for each asset; one batch needs just one data file and one command.
Search weighting on stock media platforms generally means that the match position and order of keywords affect an asset's ranking in search results. Platforms like Adobe Stock publicly state that the first several keywords (e.g., the first 10) are treated as the asset's primary description and carry more weight than subsequent keywords; the earlier a keyword appears, the more likely it is used for core retrieval matching. Contributors should therefore put the most likely buyer-typed specific nouns first and long-tail words like style, mood, and use case later. Keyword stuffing refers to submitting words that don't match the image or repeating irrelevant terms to game exposure; platforms detect this through manual spot checks and algorithmic detection, ranging from rejecting the batch to triggering an account review or even a ban.
Preventing Duplicate Uploads: A Simple Ledger
Another failure mode comes from the operator: running the same batch twice. Republishing the same asset is one of the fastest ways to get flagged on a platform. To address this, the author built upload_tracker.py, a plain-text ledger using only the standard library:
python upload_tracker.py done "asset-001.jpg"
python upload_tracker.py pending items.txt
python upload_tracker.py status
On rerun, the script checks the ledger first and skips files already marked done. It isn't clever — just a text file that remembers state. But the failure it prevents is costly, and the fix cost is minimal.
Idempotency is an important concept in batch pipelines: performing the same operation once or multiple times should have the same effect on system state. In file upload scenarios, if rerunning a script causes the same asset to be submitted multiple times, idempotency is broken, and the platform will treat it as duplicate publishing or spam submission. A text ledger is essentially lightweight state persistence: the script reads the ledger before each run and skips entries marked complete, preserving "submit once only" even after process restarts or human error. Compared with a database, its implementation cost is extremely low, yet it's sufficient for preventing low-frequency, high-cost failures like duplicate uploads.
Pure Standard Library, Runs on Low-Spec Hardware
These scripts don't need a GPU or a cloud account. make_metadata.py and upload_tracker.py are built entirely on the Python standard library and run on even the lowest-spec machine. The author's entire pipeline (including the image generation step) runs on 1 vCPU and 2 GB of RAM, one process at a time, calling gc.collect() between assets and checking real memory peaks with ru_maxrss. The CSV writer and ledger take only a small fraction of the budget.
According to the author, the parent project is about 19,000 lines of code and, on the same hardware, packaged 39 products with roughly 856 MB of output. The metadata rules derive from 300+ pages of platform validation research, with the script encoding the key parts: exact headers, ordered keywords, and no duplicate publishing.
Takeaways for AI Content Creators
These scripts may seem to serve only microstock contributors, but their principles apply to any scenario requiring batch submission of structured metadata. AI-generated content (images, audio, video) is often rejected in bulk due to format issues when submitted to distribution platforms. Encoding platform rules into checklists or scripts ahead of time can significantly reduce manual rework.
The author packaged the above scripts as the ai sticker factory playbook, containing four scripts: make_metadata.py (generating Adobe 5-column, Vecteezy 4-column, and Dreamstime 15-column CSVs), upload_tracker.py (the ledger), plus md2pdf.py and pack_product.py (converting content into sellable products with 1280×720 covers and 600×600 thumbnails). Only the latter two depend on Pillow and reportlab.
For creators building their own pipelines, these rules and tools are the crystallization of hard-learned rejection lessons. No hype — just practices that work.
One-line Summary
Microstock batch upload failures mostly stem from CSV headers and keyword ordering; encoding the rules into pure standard-library scripts solves it.
Paragraph Summary
The article recounts how a developer had 60 vector files all rejected within a minute, discovered the problem was the CSV headers rather than the files themselves, and wrote make_metadata.py to encode platform rules. The script outputs headers exactly per Adobe Stock's 5 columns, Vecteezy's 4 columns, and Dreamstime's 15 columns; uses about 15 lines of Python rules for title casing, covering 90% of cases, with the remaining 10% overridden manually via titles.json; orders keywords by importance, putting specific searchable nouns in the first 10 and long-tail words afterward, while removing mismatched keywords. An upload_tracker.py plain-text ledger prevents duplicate uploads. All scripts rely only on the standard library and run on 1 vCPU/2 GB RAM. The author believes this approach of encoding platform validation rules into scripts is equally instructive for AI content creators' batch submission pipelines.
Related articles

Chain of Thought Isn't Just for AI: How Humans Can Use CoT to Improve Thinking Quality
Chain of Thought isn't just a prompt trick for large models. Starting from a Hacker News discussion, this article analyzes why CoT works for human thinking too, breaks down actionable ways to transfer it, and highlights the key differences between human CoT and machine CoT.
Cloudflare Teams Up with OpenAI: Closi…
Cloudflare Teams Up with OpenAI: Closing the Loop from Vulnerability Discovery to Defense with AI
Cloudflare uses OpenAI Daybreak to investigate security vulnerabilities and generate reviewable remediation plans, while developers use Codex to boost coding efficiency and quality.

Orca Multi-Agent Orchestration in Practice: A Guide to Parallel Collaboration with Claude and Codex
Orca is Stable AI's free open-source agent workbench supporting 34 agents like Claude Code and Codex in parallel. Learn its Git worktree isolation, multi-model orchestration, and mobile management.