Most stock sites have picked a side on AI images. Shutterstock’s contributor program doesn’t accept them, and Getty Images has banned AI submissions since 2022. Adobe Stock does, as long as you label them, own the rights to everything in the frame, and meet the same quality bar as photographers. Every image you get accepted can keep earning royalties for years with no more work from you.
That makes it one of the few income streams that really is close to passive after the setup. The setup is the hard part: thousands of people had the same idea in 2023, the easy topics are flooded, and Adobe rejects or bans accounts that upload junk in bulk.
This guide is the version that still makes sense in late 2026:
- what Adobe actually pays, and how to estimate what a portfolio earns (spoiler: not much per image)
- a Python pipeline: prompt list → Gemini image generation → 4× upscale → Gemini writes title, 49 keywords and category → Adobe-format CSV → SFTP upload
- how to choose topics buyers actually search for, instead of the 2 millionth “futuristic city at sunset”
- costs, realistic time, and the risks: rejections, the “similar content” ban trap, copyright and tax
What Adobe pays
From Adobe Stock’s contributor pages (check contributor.stock.adobe.com before relying on these):
- 33% royalty on photos, illustrations and vectors (35% on video). Generative AI images earn the same rate as human-made ones.
- What you get per download depends on the buyer’s license. Adobe sets a minimum royalty of $0.33 per standard license on its large subscription plans, rising to $0.36 and $0.38 as your lifetime license count grows. Most subscription downloads land in the tens of cents. Extended licenses and credit-pack purchases pay more, but they’re rare.
- Payout minimum is $25, and your first payout can only happen 45 days after your first sale. Adobe pays by PayPal, Skrill or Payoneer, but its help pages list Payoneer as the required provider for Indonesia (also South Africa, South Korea and Turkey). Some Indonesian contributors say PayPal still shows up for them. Check the payout options in your own account before you count on PayPal.
- Without a valid tax form on file, Adobe withholds up to 30% for US tax. Non-US contributors fill in a W-8BEN. Indonesia has a tax treaty with the US, so filling it in correctly should lower that rate. Read the form yourself or ask a tax consultant. This blog isn’t tax advice.
- Adobe also paid a discretionary Firefly contributor bonus in September 2026 for content, including generative AI content, that was considered for training its models. You can’t plan around it. Adobe says it can’t share details of future bonuses.
Estimating what a portfolio earns
Ignore the 2023 YouTube screenshots of “$3,000/month from AI stock”. Those portfolios got in while the categories were empty, and nobody can verify them. Adobe publishes no earnings data, and contributor reports vary too much to give you a reliable table.
The number to track is revenue per image (RPI): monthly earnings divided by accepted images. Use your own dashboard to work it out once you have a few months of sales. Here’s how to use it to estimate. These numbers are examples, not promises: at $0.02 RPI, 1,000 images make $20 a month; at $0.05, $50. Many portfolios do worse than that, especially generic ones. Topic choice matters more than anything else. And as you’ll see under upload limits below, getting to 1,000 accepted images takes most new accounts many months.
The rules your images must pass
From Adobe Stock’s Generative AI content guidelines and general submission requirements:
- Label it. Tick “Created using generative AI tools” on every AI file. Unlabeled AI images get removed, and repeated cases get accounts closed.
- Size: at least 4 megapixels (for example 2450×1650), JPEG, sRGB, no more than 45 MB. Gemini’s cheap image models output about 1 MP, so you must upscale (Step 3). Adobe also says you mustn’t upscale in a way that lowers quality, so the review in Step 3 matters.
- No real people, brands, logos, trademarks, fictional characters, artist names or copyrighted works, either in the image or in prompts, titles and keywords. If an AI person appears, tick that people and property are fictional.
- Photo or illustration: submit an image as a photo only if it looks like a real camera photo, with real-world subjects and correct human and animal anatomy. Submit everything else as an illustration.
- Don’t pass AI images off as real events or newsworthy places. “Flooded street in Jakarta, January 2026” is out. “Flooded city street after heavy monsoon rain” is fine.
- Quality: no extra fingers, melted text, warped faces or upscaling artifacts. This is where most AI images get rejected.
- Spam: Adobe recommends no more than three iterations of the same concept, rejects near-duplicates as “similar content”, and may restrict or close accounts that keep sending them.
- Submission limits (since May 2025): every account has a weekly submission limit and a cap on how many files can wait in review. Adobe doesn’t publish the numbers. They change with your acceptance rate and sales. New contributors on the forums report weekly limits of around 50 files, and some hit a pause with only about 30 files pending. This is the real bottleneck for this whole business, not generation cost.
What you need
| Item | Cost | Notes |
|---|---|---|
| Adobe Stock contributor account | $0 | contributor.stock.adobe.com, uses an Adobe ID. Verify your identity early. |
| Payoneer account (or PayPal/Skrill if your account offers it) | $0 to open | For payouts. Payoneer may charge an annual fee on low-activity accounts. |
| Python 3.10+ | $0 | google-genai, pydantic, pillow |
| Gemini API key, billing on | ~$0.034 per image | aistudio.google.com. Image models have no free tier. |
| Real-ESRGAN ncnn-vulkan | $0 | github.com/xinntao/Real-ESRGAN releases. Runs on most GPUs, slowly on CPU. |
lftp | $0 | For SFTP upload (sudo apt install lftp, or brew install lftp) |
Pricing (October 2026, check ai.google.dev/pricing):
- Gemini 3.1 Flash Lite Image (
gemini-3.1-flash-lite-image, “Nano Banana 2 Lite”): output images are billed at $30 per 1M tokens, and one 1K image is 1,120 tokens = about $0.034. Batch mode halves that, but the script below uses the normal API. Google calls it its fastest and cheapest image model. It only does 1K resolution, which is why we upscale. - The older
gemini-2.5-flash-image($0.039 per image) is legacy. Google’s pricing page says it shuts down on October 2, 2026, and its deprecations page says March 15, 2027. Either way, don’t build on it. - If you’d rather skip upscaling,
gemini-nano-banana-2.1makes 2K images for about $0.05 each, which at 3:2 should land just above Adobe’s 4 MP minimum. Check the actual pixel size of your first output before relying on it. - Gemini 3.5 Flash-Lite (
gemini-3.5-flash-lite) for keywording: $0.30 per 1M input, $2.50 per 1M output. One image thumbnail plus prompt is roughly 600 input tokens and the answer about 400 output tokens, so about $0.001 per image.
Cheaper option: if you have a GPU with 12 GB+ VRAM, FLUX.1 [schnell] is Apache-2.0 licensed (commercial use allowed) and costs $0 per image locally. Swap it into Step 2 if you like. Steps 3-5 stay the same.
Step 1: Pick topics buyers search for, not topics AI is good at
This step decides your RPI, so don’t skip it.
- Open stock.adobe.com, search a concept and filter Content type → Photos. Note the result count, then exclude generative AI in the filters and compare. If a search has 500,000 results and half are AI, you’re late.
- Look for commercial concepts with few good results: things a marketer, teacher or local business would need for a slide, an ad or a blog header. Good sources of ideas are Adobe’s own Stock Trends posts, the seasonal calendar, and the search suggestions shown when you type.
- Your local advantage: Southeast Asian everyday life is still thin compared with US and European scenes. Think Ramadan iftar tables, Lebaran mudik, warung storefronts, a kos room desk setup, SME owners packing online orders, rice-field drone views, tropical home interiors. Keep these generic and don’t name real places or brands.
- Write a
prompts.txtwith one specific scene per line. Specific means you name the subject, action, setting, light and composition, and leave copy space (designers pay for empty space to put text on):
# prompts.txt - one scene per line
Young Southeast Asian woman packing online orders into cardboard boxes at a home desk, warm morning light, copy space on the right
Overhead view of an iftar table with dates, kolak, fried snacks and iced tea, family hands reaching in, soft evening light
Small grocery stall owner scanning a QR code payment on a smartphone, shallow depth of field
Empty modern tropical living room with rattan furniture and large plants, bright daylight, wide angle
Aim for 20-50 distinct concepts per batch, not 200 variations of five. Adobe recommends three iterations per concept at most. Staying at one or two is safer, and with a weekly limit of about 50 files it’s also a better use of your slots.
Step 2: Generate the images
mkdir stockai && cd stockai
python3 -m venv .venv && source .venv/bin/activate
pip install google-genai pydantic pillow
export GEMINI_API_KEY="your-paid-tier-key"
Save as generate.py:
import hashlib, os, sys, time
from pathlib import Path
from google import genai
from google.genai import errors, types
MODEL = os.environ.get("IMAGE_MODEL", "gemini-3.1-flash-lite-image")
STYLE = ("Professional commercial stock photo, realistic, natural light, sharp focus, "
"no text, no logos, no watermark, no brand names. ")
client = genai.Client()
out = Path("raw"); out.mkdir(exist_ok=True)
prompts = [l.strip() for l in open(sys.argv[1], encoding="utf-8")
if l.strip() and not l.startswith("#")]
for i, p in enumerate(prompts, 1):
name = out / (hashlib.sha1(p.encode()).hexdigest()[:10] + ".png")
if name.exists(): # safe to re-run after a crash
continue
for attempt in range(4):
try:
r = client.models.generate_content(
model=MODEL, contents=STYLE + p,
config=types.GenerateContentConfig(
response_modalities=["IMAGE"],
image_config=types.ImageConfig(aspect_ratio="3:2")))
break
except errors.APIError as e:
if e.code in (429, 500, 503) and attempt < 3:
time.sleep(15 * (attempt + 1)); continue
raise
content = r.candidates[0].content if r.candidates else None
parts = [x for x in (content.parts if content else []) if x.inline_data]
if not parts:
print(f"[{i}] no image returned (blocked?): {p[:60]}"); continue
name.write_bytes(parts[0].inline_data.data)
print(f"[{i}/{len(prompts)}] {name.name} {p[:60]}")
The script makes one image per line. The file name is a hash of the prompt, so re-running skips lines that are already done. If you want a variation, add a copy of the line with a small change like “close-up” or “wide shot”.
python generate.py prompts.txt
50 images cost about $1.70 and take a few minutes. If gemini-3.1-flash-lite-image returns a 404 or rejects the 3:2 aspect ratio, run export IMAGE_MODEL=gemini-nano-banana-2.1 and try again. Model IDs change often, so check the current list on ai.google.dev.
Step 3: Review hard, then upscale
Open raw/ in any image viewer and delete anything you wouldn’t buy. Check hands, eyes, teeth, any text-like squiggles on signs and packaging, objects merging into each other, and anything that looks like a real logo. Expect to delete 20-40%. Every bad image you upload hurts your acceptance rate, and a low acceptance rate is what gets accounts looked at.
Then upscale what’s left to 4× with Real-ESRGAN (download the ncnn-vulkan zip for your OS from the GitHub releases page and unzip it):
mkdir -p up
./realesrgan-ncnn-vulkan -i raw -o up -n realesrgan-x4plus -f png
A roughly 1 MP Gemini image (about 1248×832 at 3:2) becomes about 5000×3300. That’s too big and too smooth, so the next script scales it down to about 6 MP, which hides upscaling artifacts and still clears Adobe’s 4 MP minimum. (Our Real-ESRGAN guide covers installation and GPU issues.)
Step 4: Resize, keyword and build the CSV
Adobe lets you upload metadata as a CSV with the columns Filename, Title, Keywords, Category, Releases. Filename, Title and Keywords are required. Its rules: filenames of 30 characters or fewer, titles of 70 characters or fewer with no commas, keywords ordered by relevance, and a header row that matches Adobe’s template exactly. Category is a number from 1 to 21. The first 10 keywords count the most in search.
Save as keyword.py:
import csv, os
from io import BytesIO
from pathlib import Path
from google import genai
from google.genai import types
from PIL import Image
from pydantic import BaseModel
MODEL = os.environ.get("META_MODEL", "gemini-3.5-flash-lite")
PRICE_IN, PRICE_OUT = 0.30, 2.50 # USD per 1M tokens
TARGET_PX = 6_000_000
CATEGORIES = {1: "Animals", 2: "Buildings and Architecture", 3: "Business", 4: "Drinks",
5: "The Environment", 6: "States of Mind", 7: "Food", 8: "Graphic Resources",
9: "Hobbies and Leisure", 10: "Industry", 11: "Landscapes", 12: "Lifestyle",
13: "People", 14: "Plants and Flowers", 15: "Culture and Religion", 16: "Science",
17: "Social Issues", 18: "Sports", 19: "Technology", 20: "Transport", 21: "Travel"}
BANNED = {"ai", "generative", "generated", "gemini", "midjourney", "stock"}
class Meta(BaseModel):
title: str
keywords: list[str]
category: int
PROMPT = """You write metadata for an Adobe Stock submission. Look at the image.
title: "Sell AI Images on Adobe Stock: A Python Pipeline, Real Royalties and Upload Limits"
real people, real place names, dates or events. Do not mention AI.
keywords: 35-49 single words or short phrases, most important first: subject, action,
setting, mood, colors, and concepts a buyer would search (e.g. small business, teamwork).
No brands, no artist names, nothing about AI.
category: one number from: """ + "; ".join(f"{k}={v}" for k, v in CATEGORIES.items())
client = genai.Client()
src, dst = Path("up"), Path("final"); dst.mkdir(exist_ok=True)
rows, tok_in, tok_out = [], 0, 0
for f in sorted(src.glob("*.png")):
img = Image.open(f).convert("RGB")
scale = (TARGET_PX / (img.width * img.height)) ** 0.5
if scale < 1:
img = img.resize((round(img.width * scale), round(img.height * scale)), Image.LANCZOS)
if img.width * img.height < 4_000_000:
print(f"skip {f.name}: only {img.width}x{img.height}"); continue
out = dst / (f.stem + ".jpg")
img.save(out, "JPEG", quality=92)
thumb = img.copy(); thumb.thumbnail((768, 768))
buf = BytesIO(); thumb.save(buf, "JPEG", quality=85)
r = client.models.generate_content(
model=MODEL,
contents=[types.Part.from_bytes(data=buf.getvalue(), mime_type="image/jpeg"), PROMPT],
config=types.GenerateContentConfig(response_mime_type="application/json",
response_schema=Meta))
m, u = r.parsed, r.usage_metadata
tok_in += u.prompt_token_count or 0
tok_out += (u.candidates_token_count or 0) + (u.thoughts_token_count or 0)
kws, seen = [], set()
for k in m.keywords:
k = k.strip().lower()
if k and k not in seen and not set(k.split()) & BANNED:
seen.add(k); kws.append(k)
cat = m.category if m.category in CATEGORIES else ""
title = " ".join(m.title.replace(",", " ").split())[:70] # Adobe: <=70 chars, no commas
rows.append([out.name, title, ", ".join(kws[:49]), cat, ""])
print(f"{out.name}: {title} ({len(kws[:49])} keywords, cat {cat})")
with open("adobe.csv", "w", newline="", encoding="utf-8") as fh:
w = csv.writer(fh)
w.writerow(["Filename", "Title", "Keywords", "Category", "Releases"])
w.writerows(rows)
print(f"{len(rows)} files ready. Gemini cost: ${tok_in/1e6*PRICE_IN + tok_out/1e6*PRICE_OUT:.4f}")
python keyword.py
Read adobe.csv before you upload. Look for titles that guess a location (“Bali”, “Jakarta”), keywords for things that aren’t in the picture, and wrong categories. Irrelevant keywords count as keyword spam under Adobe’s rules, and fixing a row takes ten seconds.
Step 5: Upload by SFTP and attach the CSV
In the contributor portal, click Upload, then the Learn more link under the upload circle. That page shows the SFTP server, your user number (the username) and a button to generate an SFTP password. It’s not your Adobe ID password. If logins start failing later, generate a new one. If you don’t see the link, drag the files from final/ into the web uploader instead.
export ADOBE_SFTP_USER="1234567" # from the portal
export ADOBE_SFTP_PASS="generated-password"
lftp -u "$ADOBE_SFTP_USER","$ADOBE_SFTP_PASS" sftp://sftp.contributor.adobestock.com \
-e "mput final/*.jpg; bye"
Files appear under Uploaded files after a few minutes. Choose New, click Upload CSV, pick adobe.csv, and the titles, keywords and categories fill in for every matching filename. Then select the batch and tick “Created using generative AI tools” (and “People and Property are fictional” where it applies), and press Submit. Review usually takes from a few days to a few weeks.
Cost, time and earnings for one month
The weekly submission limit sets the pace, not your budget. Assume a new account can submit about 50 files a week, roughly 200 a month. Say you delete 30% at your own review and Adobe rejects another 30%:
| Item | Amount |
|---|---|
| Files submitted | ~200 |
| Images to generate (200 ÷ 0.7) | ~290 |
| Gemini image generation (290 × $0.034) | ~$10 |
| Keywording (200 × ~$0.001) | ~$0.20 |
| Real-ESRGAN, lftp, Adobe account | $0 |
| Accepted images at month end | ~140 |
| Your time: prompts, review, CSV check | ~6-10 hours across the month |
With local FLUX.1 [schnell] instead of Gemini, the cash cost drops to near $0 (plus electricity), but review time stays the same.
Earnings: month one, close to $0, because reviews take time and new files rank low. At this pace you have roughly 1,000-1,700 accepted images after a year, if your limit holds or grows and your acceptance rate stays decent. Using the example RPIs from the top, that’s about $20-$85 a month by month 12. Cash costs are small, so the real investment is your time. Some contributors with strong niches report more, and plenty earn less. Nobody can promise you any of these numbers.
Risks
Rejections and account restrictions. Adobe doesn’t publish an acceptance threshold, but contributors who flood the queue with weak or near-duplicate files report upload limits, slower reviews and, in repeated cases, closed accounts. Closing an account removes your whole portfolio and its income. Upload in batches that fit your weekly limit and watch your acceptance rate, which also decides whether that limit goes up or down.
Mislabeling. Forgetting the generative AI tick is the fastest way to get files pulled. Make it part of every submit.
IP and likeness. Prompts like “in the style of [artist]”, “looks like [celebrity]”, or products that resemble a known brand can produce images that infringe. Adobe forbids them, and buyers can complain after a sale. Write generic prompts and delete anything that looks like a real product.
Copyright status. In the US, the Copyright Office has said purely AI-generated images aren’t protected by copyright. That means you may not be able to stop others copying your images, and you’re relying on Adobe’s terms rather than copyright to sell them. Adobe accepts this. Just don’t expect strong legal protection.
Model terms. Google’s Gemini API terms let you use the outputs commercially, but you remain responsible for them. Images made with Gemini carry an invisible SynthID watermark, which is fine because you’re labeling them as AI anyway. Don’t use the free tier for anything you care about. Its data terms are different.
Policy change. Adobe can change its AI rules or royalty rates at any time, as Shutterstock and Getty did by closing the door. Treat this as one stream, not your only one.
Reality check
What doesn’t work:
- Generic prompts. “Beautiful sunset over mountains”, “cyberpunk city”, “cute cat”. These categories have hundreds of thousands of AI images, and yours will sit on page 200.
- Volume as a strategy. 5,000 near-duplicates get rejected as similar content and put your account at risk. 500 distinct, useful concepts earn more.
- Text in images. Signs, menus, packaging. Models still garble it, and reviewers reject it.
- Fantasy art and wallpapers. Pretty, but few buyers license them. Stock buyers need images for slides, ads, articles and packaging.
- Expecting quick money. If you need income this month, sell a service like subtitle translation or PDF-to-Excel gigs and build the portfolio on the side.
Common mistakes:
- Uploading without reviewing at 100% zoom, especially hands and faces
- Leaving location names or “AI” in titles and keywords
- Burying the main subject at keyword #30 instead of the top 10
- Never checking which images sell. Look at your sales in the contributor dashboard each month and make more of what sells, in new variations, not copies.
- Skipping the W-8BEN tax form and losing up to 30% to withholding
Model names change. If gemini-3.1-flash-lite-image or gemini-3.5-flash-lite gets retired, set IMAGE_MODEL / META_MODEL to the current model and update the prices in keyword.py.
Final checklist
- Contributor account verified, tax form filled, payout account connected (Payoneer in Indonesia)
- 20-50 distinct, searched-for concepts in
prompts.txt, each with copy space - Generated, reviewed at 100% zoom, rejects deleted
- Upscaled, resized to ~6 MP,
adobe.csvchecked by hand - Uploaded by SFTP, CSV attached, generative AI box ticked on every file
- Acceptance rate and sales checked before the next batch
Start today: spend 30 minutes on stock.adobe.com searching ten Southeast Asian everyday-life concepts, write down the five with the fewest good results, and turn them into your first prompts.txt. Your first batch of 50 costs under $2 and can be in review tonight, as long as it fits your submission limit.