ScreenshotNeo

BlogHow-to

How to Fix a URL Encoding Error in the Cloudinary Website Screenshot API

Diagnose Cloudinary screenshot URL errors by inspecting the response, encoding the target URL in the right context, and checking URL structure and access.

By the ScreenshotNeo team4 October 20268 min read

If a Cloudinary website screenshot request fails with a URL encoding error, inspect its HTTP status and X-Cld-Error response header first. Then check which URL layer is malformed: the target website address embedded in the screenshot request, or Cloudinary’s own delivery URL. Encode reserved characters for the component that contains the target URL, preserve Cloudinary’s documented URL component order, and avoid double-encoding the entire address.

The screenshot example in Cloudinary’s older URL2PNG article places a target URL’s question mark in encoded form (%3F) and says Cloudinary client libraries encode special characters for that use case. Treat it as a legacy example: verify whether URL2PNG and the workflow are currently available for your account before relying on them. Cloudinary’s URL2PNG article is useful for understanding the nested-URL issue, while current requirements should come from current Cloudinary documentation.

1. Identify which URL is failing

A screenshot integration can involve at least two distinct URLs:

  • Target URL: the page the screenshot service is asked to capture, such as https://example.com/search?q=blue+shoes&page=2#results.
  • Cloudinary delivery URL: the URL used to deliver a Cloudinary asset or transformed result. Its path has Cloudinary-specific components and may also include transformations, a version, and a public ID.

Do not change both at once. First copy the failed request from the browser Network panel or application log. Determine whether the target URL is a query parameter, a path component, or a value generated by a Cloudinary SDK. Next inspect the actual response status and headers. A malformed nested target URL and a malformed Cloudinary delivery path can both look like “encoding” problems, but they need different fixes.

2. Read the status and X-Cld-Error

  1. Open Developer Tools and select the Network tab.
  2. Reproduce the failing request and select the request with the error status.
  3. Record the request URL, status code, and X-Cld-Error response header.
  4. If your client hides response headers, make the same request with a command-line HTTP client and inspect its headers.

Cloudinary documents X-Cld-Error as a way to understand delivery and transformation failures. Some accounts may be configured to return JSON, HTML, a fallback image, or a classic header-based error, so do not assume an error body will always be present. See Cloudinary’s transformation troubleshooting guide and error handling documentation.

Signal Likely area to inspect Next action
400 Bad Request Invalid URL syntax, malformed transformation, unsupported or conflicting parameter Read X-Cld-Error; validate encoding and URL component order.
401 Unauthorized Access restriction, private/authenticated asset, restricted feature, or required signature Check current account and asset requirements; sign on a trusted server if required.
404 Not Found Missing asset/public ID or malformed Cloudinary path order Verify the Cloudinary resource and compare the URL to its documented structure.

These are diagnostic categories, not a guarantee that every account or workflow returns identical messages. Cloudinary’s current error guidance describes common 400, 401, and 404 cases in its error-code reference.

3. Encode the target URL in the correct context

Reserved characters such as ?, &, and # have structural meaning in URLs. When a target address is embedded inside another URL, its characters may need encoding so they remain data rather than being interpreted as separators by the outer request. The exact operation depends on where the inner URL is placed. Query parameters should be encoded as query parameter values; path components have different rules.

Prefer the current Cloudinary SDK/helper for the screenshot workflow when that SDK supports it. The Cloudinary URL2PNG example says Cloudinary client libraries automatically encode special characters for its use case. If constructing a URL manually, use a URI library appropriate to the containing component rather than replacing characters with ad hoc string substitutions. Inspect the generated URL before sending it.

Example: safely build a query string with Python

This generic Python example shows how to encode a target URL as the value of an outer query parameter. Replace the endpoint and parameter name with those required by the specific Cloudinary workflow you are using; it is not a claim about a current Cloudinary screenshot endpoint.

from urllib.parse import urlencode

endpoint = "https://service.example/screenshot"
target = "https://example.com/search?q=blue+shoes&page=2#results"
request_url = endpoint + "?" + urlencode({"url": target})
print(request_url)

Use a URL builder like this only when the API expects the target in a query parameter. If the target is embedded in a path or transformation component, use the SDK/helper or the encoding rules documented for that exact component.

Example: safely build a query string with Node.js

const endpoint = new URL("https://service.example/screenshot");
const target = "https://example.com/search?q=blue+shoes&page=2#results";
endpoint.searchParams.set("url", target);
console.log(endpoint.toString());

Again, this demonstrates generic query-parameter construction. Do not treat it as a Cloudinary endpoint specification. Use the current Cloudinary documentation and SDK for the actual workflow and verify the produced URL.

4. Check Cloudinary URL structure separately

A Cloudinary delivery URL has this documented general order:

https://res.cloudinary.com/<cloud_name>/<asset_type>/<delivery_type>/<transformations>/<version>/<public_id_full_path>.<extension>

Compare the failing delivery URL with Cloudinary’s transformation URL reference. Confirm that the cloud name, asset type, delivery type, transformations, version, and public ID are in their expected positions. In particular, check that transformation text was not appended after the public ID. SDK transformation names and syntax may differ from raw URL API syntax, so do not copy a URL API parameter into an SDK call without checking that SDK’s documentation.

5. Avoid the common double-encoding mistake

Cloudinary’s text-overlay documentation has specific UTF-8 escaping rules for text values, and some text overlay values can require double encoding. Those rules apply to text overlay components. They are not a universal instruction to double-encode an entire screenshot target URL.

Double encoding can turn an intended separator such as ? into the literal text %3F after one decoding pass, leaving the target address incorrect. Encode once for the outer URL component that contains the target, unless the documentation for that exact component explicitly requires another encoding layer. Keep a copy of the original target and compare it with the decoded value received by the service.

6. Diagnose by response

400 Bad Request

  • Read the full X-Cld-Error; it may point to invalid syntax, a parameter value, or conflicting transformations.
  • Check whether reserved target URL characters were encoded for their containing component.
  • Confirm that transformations precede the version and public ID in the Cloudinary delivery URL.
  • Check for accidental double encoding, missing separators, and string concatenation that dropped or added a question mark.
  • Change one thing at a time and retry so the cause remains clear.

401 Unauthorized

  • Check whether the asset is private or authenticated, a strict transformation needs a signature, or the feature is restricted for the account.
  • If a signature is needed, generate it with a trusted server-side implementation and keep the API secret out of browser JavaScript.
  • Use current Cloudinary SDK documentation for the signing procedure for your language and workflow; requirements vary by use case.

404 Not Found

  • Verify that the Cloudinary asset exists in the expected cloud and that the public ID and extension are correct.
  • Check for a misplaced cloud name, resource type, delivery type, transformation, version, or public ID.
  • Keep the source website URL distinct from the Cloudinary asset URL: a valid target page does not prove the delivered asset exists.

7. Keep a reproducible debugging record

For each failed attempt, save the original target URL, generated request URL, status code, X-Cld-Error, and the change made. Remove credentials or signed values before sharing logs. Retest after changing a single variable. If a corrected request still returns the old failure, check whether a cached error response is involved and consult the current Cloudinary delivery error guidance.

8. Performance, reliability, and cost considerations

  • Build URLs once and inspect them. A standard URL builder or SDK helper reduces mistakes compared with manual concatenation, especially when a target contains multiple query parameters or a fragment.
  • Keep signatures server-side. Browser-side secrets can expose credentials; signing should follow the current Cloudinary security guidance for the chosen workflow.
  • Separate request construction from capture failure. A correctly encoded URL can still fail because the target page is unavailable, protected, slow, or unsupported. The HTTP response and error header help distinguish delivery syntax from other failures.
  • Do not infer billing from an HTTP status alone. Confirm current URL2PNG/add-on availability, account requirements, and pricing in Cloudinary’s current product documentation; the legacy article does not establish present-day terms.

Or skip the browser setup

If your goal is simply to get a website screenshot, ScreenshotNeo is a website screenshot API and MCP server. It accepts a URL in one GET request and returns PNG, JPEG, WebP, or PDF. The request below follows the supplied API format; read the ScreenshotNeo API documentation for options.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const image = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', image));
  • Cookie and consent banners are accepted and removed before capture; newsletter popups and chat widgets are also removed. Each step can be turned off.
  • Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed; response headers identify the page verdict and billing status.
  • An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents and MCP clients.
  • The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots.

Sign up for ScreenshotNeo’s free plan and get 1,000 screenshots a month with no card.

FAQ

Should I encode every character in the target URL?

No. Encode the target as required by the component that contains it. A query parameter builder handles query-value encoding; path and transformation components have their own rules.

Does a 400 response prove the target URL encoding is wrong?

No. Cloudinary also documents invalid or conflicting transformation syntax as possible causes. Use the status and X-Cld-Error to narrow down the failing layer.

Can I use Cloudinary’s text-overlay double-encoding rules for the screenshot URL?

Not by default. Those instructions apply to text-overlay values, not all embedded target URLs.

Is the URL2PNG example guaranteed to work for a new Cloudinary account?

No. It is from an older article. Check current add-on availability and account requirements before adopting its exact workflow.

References