Reference
Responses and errors
The answer envelope, every error the API can send back, and how to handle each one.
Every answer from the API has the same shape, whether the capture worked or not. Your code reads the same four fields every time.
EnvelopeLink to this section
successbooleanAlwaystruewhen the screenshot was created,falsefor every error.codenumberAlwaysThe HTTP status of the answer, repeated in the body.
messagestringAlwaysWhat happened, in plain words. Safe to show to your own users.
dataobject | nullAlwaysThe result on success.
nullon most errors, or the list of what is wrong when fields are missing.
The HTTP status of the answer is always the same as code, so you can check either one.
SuccessLink to this section
A finished capture answers with status 200, and data holds the hosted link and the image itself.
{
"success": true,
"code": 200,
"message": "Screenshot was generated.",
"data": {
"scrUrl": "https://.../screenshots/.../8f3c2a91d4e5b6c7.png",
"scrBase64": "iVBORw0KGgoAAAANSUhEUgAA..."
}
}ErrorsLink to this section
An error answers with success set to false, a matching status and a readable message. data is usually null.
{
"success": false,
"code": 401,
"message": "User is not authorized to create screenshot!",
"data": null
}When required fields are missing, data lists them:
{
"success": false,
"code": 400,
"message": "Missing parameters on the payload please include all the required values!",
"data": ["token"]
}Error messagesLink to this section
These are every message the screenshot endpoint can send back. The wording never changes, so it is safe to match on, and it is written to be shown to your own users as it is.
- 400
Inital request missing required parameters!
The request was not sent as JSON.
datasays what is wrong with theContent-Typeheader. - 400
Missing parameters on the payload please include all the required values!
urlortokenis missing.datalists the missing fields. - 401
User is not authorized to create screenshot!
The token does not belong to any account, or it was regenerated.
- 402
URL is not valid, please check the link!
The
urlcould not be read as a web address. - 400
You don't have enough credits to generate a screenshot!
The balance is lower than the cost of the capture.
- 405
This method is not allowed!
The request was not a
POST. - 429
You cannot start more than 3 concurrent screenshots. If you want to increase the limit contact support!
Too many captures are already running for the account. The number is your own limit.
- 400
Screenshot was not generated because of a problem!
The page could not be captured. The credits are returned.
- 503
The screenshot service is not available right now, please try again later!
The capture browser is temporarily unavailable. No credits are used.
- 500
Screenshot was not generated because of a problem!
Something failed on our side. The credits are returned.
Handling errorsLink to this section
- Check
successfirst. When it isfalse, show or logmessage. 401,402,405and the missing field errors need a change to the request. Sending it again as it is gives the same answer.429means your captures in progress are at your limit. Wait for one to finish, or see limits.503is temporary. Try again after a short wait, with a longer wait each time.- When a page cannot be captured, try a later
takeScreenshotWhenstep or awaitBeforeScreenshot. Your dashboard shows why each capture failed.
A small retry helper for the temporary errors:
const RETRY = new Set([429, 503])
async function capture(body, attempt = 1) {
const response = await fetch('https://url2image.modulify.website/api/screenshots/create', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body)
})
const result = await response.json()
if (result.success) return result.data
// Busy or briefly unavailable: wait a little longer each time
if (RETRY.has(result.code) && attempt < 3) {
await new Promise(resolve => setTimeout(resolve, attempt * 5000))
return capture(body, attempt + 1)
}
throw new Error(result.message)
}Something unclear or missing on this page?
Tell us