Upscale Images
January 2, 2026 (October 5, 2026)
Table of contents
Upscale a previously generated image to 2K or 4K resolution. This endpoint uses Google Flow’s native image upscaling capabilities.
Seeing “Upscaling failed” in Flow? Why Google Flow upscales fail and how to fix it.
Important:
2kworks on every plan, including free accounts.4krequires a Google AI Ultra subscription. Every other plan, free, Plus and Pro alike, is limited to2kand a4krequest answers400with4k upscaling is not available for this account. The request is refused before a reCAPTCHA token is solved, so it costs you nothing — raisingcaptchaRetrywill not change the outcome.- Both resolutions are free of Google Flow credits.
https://api.useapi.net/v1/google-flow/images/upscale
Request Headers
Authorization: Bearer {API token}
Content-Type: application/json
# Alternatively you can use multipart/form-data
# Content-Type: multipart/form-data
API tokenis required, see Setup useapi.net for details.
Request Body
{
"mediaGenerationId": "user:12345-email:6a6f...-image:CAMaJDMx...",
"resolution": "2k"
}
mediaGenerationIdis required. ThemediaGenerationIdfrom a previously generated image via POST /images.resolutionis optional. Target resolution for upscaling (default:2k). Supported values:2k,4k.captchaToken,captchaRetry,captchaOrderare optional, mutually exclusive captcha parameters. See Captcha Parameters for details.
Responses
-
Image upscaled successfully. Returns base64-encoded image data.
{ "encodedImage": "/9j/4AAQSkZJRgABAQAAAQ...base64 encoded image data...", "captcha": { "service": "AntiCaptcha", "taskId": "abc123...", "durationMs": 3500, "attempts": [ { "service": "AntiCaptcha", "taskId": "abc123...", "durationMs": 3500, "success": true } ] } } -
Invalid request (missing or invalid mediaGenerationId), or
4kon an account without Google AI Ultra.{ "error": "4k upscaling is not available for this account", "code": 400 } -
Invalid API token.
{ "error": "Unauthorized" } -
Google rejected the captcha on every try. We retry with a fresh captcha as many times as you allow (
captchaRetry, default 5, or the providers incaptchaOrder) and return this403only when all of them were rejected. The top-levelerrorstarts withcaptcha_quality:, for example"captcha_quality: PUBLIC_ERROR_UNUSUAL_ACTIVITY after 5 attempts — see GET /accounts/captcha-stats summary.by_account".One
403is not a captcha problem.PUBLIC_ERROR_MODEL_ACCESS_DENIEDin the response means Google refused the model on that account, so raisingcaptchaRetryor adding providers will not help. Check that the account’s plan includes the model. Since 2026-09-23 Google no longer offersveo-3.1-lite-low-priorityto invited members of an Ultra $199 family plan — only the family manager’s account keeps it.Nothing was created when this happens. Google checks the captcha before it starts generating, so no Google credits were used and you can resubmit straight away. Your captcha provider still bills each solve.
The usual cause is the Google account, not the captcha provider. Google gives each account its own trust level. On a trusted account it accepts about 9 in 10 captchas, on a distrusted one about 3 in 10, whichever provider solved them. Most customers have a few distrusted accounts among many good ones.
To see which accounts are affected, use GET /accounts/captcha-stats. Its
summary.by_accountshows, for each of your Google accounts, how many captchas were tried and what share Google accepted. GET account/stats withbot=google-flowalso shows how many requests each account finished with each response code.- If one or a few accounts are far below the others, the API already sends them less work: when you leave out
email, each captcha Google rejected on an account in the last 15 minutes lowers its chance of being picked, for generations and for image uploads. They still get some work, so an account that recovers gets its full share back. If you pin requests withemail, move them to your other accounts yourself. Replace an account that stays low for more than a day or two. - If all your accounts drop at the same time, it’s the captcha provider. Configure at least two providers with POST /accounts/captcha-providers, and the API will start with whichever one Google accepts best.
A higher
captchaRetrygets more requests through on a distrusted account, but every extra try is another paid solve. - If one or a few accounts are far below the others, the API already sends them less work: when you leave out
-
Account not found or image not found.
{ "error": "Google Flow account [email protected] not found" } -
Google returns several
RESOURCE_EXHAUSTED429 variants. Check thereasonfield and respond accordingly:Reason Meaning Scope What to do Cooldown PUBLIC_ERROR_USER_REQUESTS_THROTTLEDGoogle is throttling the account (the token was fine). Uploads and generation are metered separately All models on the account — or uploads only, when POST /assets triggered it Run fewer parallel requests, or switch accounts. From POST /assets, retrying the same one rarely clears it ~30 min. From POST /assets, treat it as a minimum — it can persist PUBLIC_ERROR_USER_QUOTA_REACHEDAccount’s overall Flow quota cap All models on the account Add accounts, or omit emailto load-balance~30 min PUBLIC_ERROR_PER_MODEL_DAILY_QUOTA_REACHEDPer-model daily quota Only that model, on that account Switch model, or wait Next UTC midnight PUBLIC_ERROR_UNUSUAL_ACTIVITY_TOO_MUCH_TRAFFICGoogle rejected the captcha on every try (we already retried). Usually a distrusted Google account, sometimes the provider Per request Check which accounts are affected in captcha-stats. Rest or replace those accounts. Add a second provider if all accounts drop together 60s Every
429returns the cooldown two ways — an HTTPRetry-After: <seconds>header and a bodyretryAfter: <ISO timestamp>field. Honor it before retrying.When
emailis omitted, the first three reasons quarantine the account and the load balancer routes around it. If every account is quarantined for the model you get429witherror: "no_eligible_account". Routing details: GET /jobs › Load Balancing Algorithm.Captcha-quality failures prefix the top-level
errorwithcaptcha_quality:(e.g."captcha_quality: PUBLIC_ERROR_UNUSUAL_ACTIVITY_TOO_MUCH_TRAFFIC after 3 attempts") so you can detect them without parsing the nested body. -
503has two distinct causes — check the response body to tell them apart.A transient Google-side outage. Wait 5-10 seconds and retry.
{ "error": { "code": 503, "message": "Service temporarily unavailable.", "status": "UNAVAILABLE" } }A captcha-provider failure — the top-level
erroris prefixedCaptcha service failed:. The problem is your captcha provider (check its API key and balance), not Google. Don’t retry until the provider is back.{ "error": "Captcha service failed: ERROR_ZERO_BALANCE", "code": 503 }
Model
encodedImage- Base64-encoded upscaled image data (JPEG format)captcha- Captcha metadata for debugging/researchcaptcha.service- Provider that returned the successful tokencaptcha.taskId- Task ID from the captcha servicecaptcha.durationMs- Total time for all captcha attemptscaptcha.attempts- Array of all captcha attempts (including failures)
{
encodedImage: string // Base64-encoded image (decode and save as .jpg)
captcha?: { // Captcha metadata
service: string // "CapSolver" | "AntiCaptcha" | "YesCaptcha" | "CapMonster" | "SolveCaptcha" | "2Captcha" | "EzCaptcha" | "UserProvided"
taskId?: string
durationMs: number
attempts: Array<{
service: string
taskId?: string
durationMs: number
success: boolean
error?: string
}>
}
error?: string | { // Error: string (useapi.net) or object (Google API)
code: number
message: string
status: string
details: Array<{
'@type': string
reason: string
}>
}
}
Examples
-
# First generate an image curl -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{"prompt": "A beautiful sunset over mountains"}' \ "https://api.useapi.net/v1/google-flow/images" > generate.json # Extract mediaGenerationId from the response MEDIA_ID=$(jq -r '.media[0].image.generatedImage.mediaGenerationId' generate.json) # Upscale the image to 2K curl -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"mediaGenerationId\": \"$MEDIA_ID\", \"resolution\": \"2k\"}" \ "https://api.useapi.net/v1/google-flow/images/upscale" > upscale.json # Decode base64 and save as image jq -r '.encodedImage' upscale.json | base64 -d > upscaled_image.jpg -
const token = 'YOUR_API_TOKEN'; // First generate an image const generateResponse = await fetch('https://api.useapi.net/v1/google-flow/images', { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ prompt: 'A beautiful sunset over mountains' }) }); const generated = await generateResponse.json(); const mediaGenerationId = generated.media[0].image.generatedImage.mediaGenerationId; // Upscale the image const upscaleResponse = await fetch('https://api.useapi.net/v1/google-flow/images/upscale', { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ mediaGenerationId, resolution: '2k' }) }); const upscaled = await upscaleResponse.json(); // Decode base64 and save const buffer = Buffer.from(upscaled.encodedImage, 'base64'); require('fs').writeFileSync('upscaled_image.jpg', buffer); console.log('Upscaled image saved!'); -
import requests import base64 token = 'YOUR_API_TOKEN' headers = { 'Authorization': f'Bearer {token}', 'Content-Type': 'application/json' } # First generate an image generate_response = requests.post( 'https://api.useapi.net/v1/google-flow/images', headers=headers, json={'prompt': 'A beautiful sunset over mountains'} ) generated = generate_response.json() media_generation_id = generated['media'][0]['image']['generatedImage']['mediaGenerationId'] # Upscale the image upscale_response = requests.post( 'https://api.useapi.net/v1/google-flow/images/upscale', headers=headers, json={ 'mediaGenerationId': media_generation_id, 'resolution': '2k' } ) upscaled = upscale_response.json() # Decode base64 and save image_data = base64.b64decode(upscaled['encodedImage']) with open('upscaled_image.jpg', 'wb') as f: f.write(image_data) print('Upscaled image saved!')