How to Hide Webpage Ads in Cloudinary Screenshots
Cloudinary URL2PNG documents capture settings, but not ad removal. Use Playwright to hide page-specific ad elements, or choose a screenshot API with CSS controls.
Cloudinary’s URL2PNG add-on captures public websites and sends the resulting screenshot into Cloudinary’s media pipeline. Its documented settings include viewport, user agent, delay, and full-page capture, but the documentation does not list an option to hide ads or inject custom CSS. For ad-free captures, use browser automation such as Playwright and hide known ad containers with a stylesheet before taking the screenshot. That is a browser automation workflow, not a Cloudinary URL2PNG setting.
If you need a managed screenshot API instead, ScreenshotNeo is an alternative to try first: it removes known ads and other unwanted elements before capture, bills only clean shots, and its paid plans start at $5.
What Cloudinary URL2PNG can and cannot do
Cloudinary documents URL2PNG as a website screenshot add-on. Its examples show configuring capture properties such as viewport, user agent, delay, and full-page behavior when generating a screenshot. Those settings control how the page is captured; the documentation located does not describe an ad-blocking option or a way to inject arbitrary CSS.
Check the current Cloudinary URL2PNG documentation and your account configuration for supported options. Do not assume that a guessed URL parameter will hide ads. If you already use URL2PNG and need ad elements removed, run the capture in a browser you control, or use a separate screenshot service that documents styling or ad blocking. Playwright’s stylesheet injection is one such self-managed route.
Hide page-specific ads with Playwright
Playwright supports applying CSS at screenshot time with the style or stylePath option. A stylesheet can hide dynamic elements; Playwright documents that this styling pierces Shadow DOM and inner frames. The selectors below are examples only: advertising markup differs by website, so identify and verify the selectors for the page you capture.
1. Set up the project
mkdir clean-capture
cd clean-capture
npm init -y
npm install playwright
npx playwright install chromium
2. Create an ad-hiding stylesheet
Save this as hide-ads.css. Replace the example selectors with selectors confirmed in the target page’s DOM. Avoid broad rules such as hiding every iframe, aside, or element whose class contains “ad”; those can remove video, navigation, or legitimate article content.
/* hide-ads.css */
.adsbygoogle,
[data-ad-slot],
.advertisement,
.ad-container {
display: none !important;
visibility: hidden !important;
}
3. Capture with the stylesheet applied
Save as capture.mjs and replace the URL and selectors with the actual target. The page is allowed to load network resources before capture; the injected styles affect the screenshot rendering.
import { chromium } from 'playwright';
const url = 'https://example.com';
const browser = await chromium.launch({ headless: true });
const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
try {
await page.goto(url, { waitUntil: 'networkidle', timeout: 45_000 });
await page.screenshot({
path: 'page.png',
fullPage: true,
stylePath: './hide-ads.css',
});
} finally {
await browser.close();
}
Run it with node capture.mjs. If a page never becomes network-idle because of analytics or long polling, use waitUntil: 'domcontentloaded' and a deliberate short wait or wait for a page-specific content selector before capturing. The stylesheet option is documented by Playwright; selector choice and capture timing need to be adapted to the site.
Alternative: inject CSS from JavaScript
For a small one-off script, use the screenshot style option instead of maintaining a file:
await page.screenshot({
path: 'page.png',
fullPage: true,
style: `
.adsbygoogle,
[data-ad-slot],
.advertisement {
display: none !important;
visibility: hidden !important;
}
`,
});
See the Playwright screenshot API documentation for the version-specific options. The stylesheet injection is applied for the screenshot, rather than being a Cloudinary option.
Choosing selectors safely
- Inspect the page’s DOM in browser developer tools and identify the smallest container that holds the ad.
- Prefer stable attributes or site-specific classes over generic tags. A selector such as
[data-ad-slot]is useful only if that target site actually uses it. - Capture a test image and inspect it at normal size. Check that the ad is gone and that article text, images, navigation, and consent controls you need remain.
- Maintain selectors per site when markup changes. There is no universal CSS selector that reliably identifies ads across websites.
cURL, Python, and Node.js options
Cloudinary’s URL2PNG integration is configured through its documented add-on and URL construction; its documentation does not provide a generic cURL, Python, or Node.js CSS injection parameter. You can call a browser automation script from another application, or use a screenshot API whose documented options include CSS. For example, ScreenshotNeo accepts CSS-related capture options and can remove known unwanted elements before taking the shot. Its API documentation lists the supported parameters.
cURL
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://stripe.com \
-o shot.webp
Python
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()
with open("shot.webp", "wb") as f:
f.write(r.content)
Node.js
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}`);
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer())));
The examples show the one-call capture shape. To hide a particular ad selector using a service, consult that service’s parameter documentation and use its actual CSS option names; do not assume Cloudinary supports those parameters. ScreenshotNeo supports custom CSS and JavaScript, hiding selectors, blocking ads and resources, full-page captures, element capture, waits, and other options. Each step can be turned off. Consult its docs for exact parameters and supported formats.
Or skip the browser setup
Use a managed screenshot API when you do not want to maintain a browser and selector script. ScreenshotNeo’s API returns a screenshot from one GET request; see the API docs for capture parameters.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Cookie banners, popups, and chat widgets are removed before the shot; bot checks, blank pages, and failed loads are never billed. An MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000. Sign up for 1,000 free screenshots a month.
Other approaches and trade-offs
| Approach | Where ad handling happens | Control and operations |
|---|---|---|
| Cloudinary URL2PNG | Documented capture settings; no ad hiding or arbitrary stylesheet control was found in the cited documentation. | Fits an existing Cloudinary media workflow. Verify supported options in Cloudinary’s current docs and account. |
| Playwright | CSS is applied in the browser during screenshot capture. | Fine-grained, page-specific selectors; you maintain browser setup, selector rules, and capture execution. |
| Screenshot API with CSS or ad controls | The provider handles the browser and applies documented capture controls. | Less browser infrastructure to operate. Check its current options, pricing, privacy terms, and behavior independently. |
Another hosted provider, ScreenshotCore, advertises ad and resource blocking plus custom CSS and JavaScript injection. This is a separate service from Cloudinary; those capabilities are the provider’s statements, not independent test results. Compare documentation, pricing, data handling, and suitability before choosing any hosted service.
Performance, reliability, and cost
- Wait strategy affects speed.
networkidlecan be slow or never occur on pages with persistent network activity. A content selector or a bounded wait can make capture timing more predictable, but choose a condition that reflects when the content you need is ready. - Full-page captures take more work. Long pages may require more browser rendering and produce larger files than viewport captures. Use a viewport screenshot if that is all the downstream task needs.
- Selectors can go stale. A site redesign can change ad markup, leaving ads visible or causing a selector to hide unrelated content. Review representative output periodically and after page changes.
- Browser automation adds operational work. Pin and update Playwright deliberately, install its browser runtime in deployment, close browser instances in cleanup paths, and set navigation timeouts. A hosted API shifts browser execution to a provider but introduces provider terms and request limits to evaluate.
- Cloudinary costs are account-specific. The research does not establish URL2PNG pricing. Check Cloudinary’s current add-on and account terms rather than assuming a price.
- ScreenshotNeo pricing is stated by the service. Free: 1,000 shots/month; Starter: $5 for 3,000; Growth: $15 for 15,000; Pro: $39 for 60,000; Scale: $99 for 250,000; Business: $249 for 1,000,000. Yearly billing gives two months free, and every feature is on every plan. Its response includes page-verdict and billed headers; clean shots are billed, while bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Ads remain in the Playwright image | The selector does not match the page, the ad is in a different container, or the page changed. | Inspect the live DOM, verify the selector against the actual ad element, then capture and review again. Do not assume a generic class exists. |
| Legitimate content disappears | The CSS selector is too broad and matches non-ad elements. | Narrow it to the specific ad container and recheck article content, navigation, and embeds in the output. |
| Playwright times out during navigation | The page keeps network connections open or is slow to load. | Use a bounded timeout and a more suitable readiness condition such as domcontentloaded; wait for a specific content selector if needed. |
| Cloudinary output still contains ads | The documented URL2PNG settings control capture properties, and the cited documentation does not list ad hiding or CSS injection. | Use a browser automation stylesheet workflow or a separate service with documented ad/CSS controls. Do not add undocumented URL parameters. |
| The API response is not an image | The request may have returned an error response or a page verdict instead of a normal capture. | Check the HTTP status and response headers before saving the body as an image. For ScreenshotNeo, inspect X-Page-Verdict and X-Billed as documented service response indicators. |
| Node.js reports an unsupported option | The installed Playwright version may differ from the documentation version for style or stylePath. |
Check the API docs for your installed version and upgrade or use the styling option supported by that version. |
FAQ
Can Cloudinary URL2PNG remove ads by itself?
The documentation located describes capture options but does not list ad blocking or stylesheet injection. Confirm current behavior and options in Cloudinary’s documentation for your account.
Can I block ad network requests instead of hiding ad elements?
That is a different approach. Browser automation can be configured to intercept or block requests, and some hosted screenshot APIs advertise resource blocking. The dossier does not establish a Cloudinary URL2PNG request-blocking setting.
Will one selector work on every site?
No universal selector is established by the sources. Inspect each target and validate captures so that wanted content remains.
Can the same technique remove cookie banners and chat widgets?
With Playwright, you can add site-specific selectors to the injected stylesheet, subject to the same inspection and validation. ScreenshotNeo states that it removes known consent platforms, newsletter popups, and chat widgets before capture, and each step can be turned off.


