# Blocking ads, cookie banners, trackers and chats

Remove ads, consent pop-ups, tracking scripts and chat widgets before the capture, and block any other request by type or pattern.

Four options clear away the usual clutter.

```bash
curl "https://curlshot.com/api/v1/screenshot?access_key=YOUR_ACCESS_KEY\
&url=https://en.wikipedia.org/wiki/Eiffel_Tower\
&block_ads=true\
&block_trackers=true\
&block_cookie_banners=true\
&block_chats=true" \
  --output eiffel-clean.png
```

You get the page without ad slots, consent pop-ups or chat bubbles, where the site had any. On a page with none of these, the screenshot is the same as before.

## How blocking works

A web page is not one file. The browser fetches dozens of extra files: scripts, images, fonts, ads. Each fetch is called a request.

Blocking stops some of those requests before they leave the browser. An ad whose script never loads never appears. As a bonus, the page often renders faster.

The page you asked for is never blocked. Only the extra files it pulls in are checked.

All four switches are off by default, so a plain request shows the page as a first-time visitor sees it.

## The four switches

### block_ads

Stops requests to known advertising networks.

The default is `false`.

Use it for clean previews and thumbnails. The space an ad would have filled may stay empty, depending on how the site is built.

### block_trackers

Stops known analytics and tracking scripts. These record visits and do not usually draw anything.

The default is `false`.

The screenshot rarely changes. The gain is speed, and your captures do not show up as visits in the site's statistics.

### block_cookie_banners

Removes cookie consent pop-ups.

The default is `false`.

It works in three ways. It stops the scripts of well-known consent tools from loading. It hides the banner layouts those tools use. And for a banner it does not recognise, it looks for a consent dialog and presses one of its buttons to close it.

### block_chats

Stops live-chat widgets, the "Can I help you?" bubbles in the corner.

The default is `false`.

## Block a whole kind of file

### block_resources

Blocks every request of the given types.

There is no default. Leave it out and nothing is blocked by type.

The allowed values are `document`, `stylesheet`, `image`, `media`, `font`, `script`, `xhr`, `fetch`, `websocket`, `texttrack`, `eventsource`, `manifest` and `other`.

This is a list option. Separate the values with commas.

```bash
curl "https://curlshot.com/api/v1/screenshot?access_key=YOUR_ACCESS_KEY&url=https://github.com/microsoft/playwright&block_resources=font,media" \
  --output playwright-light.png
```

The page is drawn with fallback fonts, and video and audio files are never fetched.

The most useful values:

| Value | What is blocked | What you will notice |
| --- | --- | --- |
| `media` | Video and audio files. | Faster renders on pages with background video. |
| `font` | Web fonts. | Text in a standard font. |
| `image` | All images. | Empty boxes where images were. |
| `script` | All JavaScript. | Many modern sites stay blank or half-built. |
| `stylesheet` | All CSS files. | An unstyled page. |

`document` covers pages embedded inside the page, such as iframes. `xhr` and `fetch` are the data requests a page makes after it has loaded.

> **Heads up**
>
> `script` and `stylesheet` change pages a lot. Use them only when you know the site works without them.

## Block specific addresses

### block_requests

Blocks requests whose address matches one of your patterns.

There is no default. Leave it out and no pattern is applied.

A pattern is a piece of text with an optional `*` wildcard. The `*` stands for any run of characters.

| Pattern | What it blocks |
| --- | --- |
| `newsletter-popup` | Any address that contains this text. |
| `*.example.com/ads/*` | Everything under `/ads/` on any subdomain of example.com. |
| `*/promo.js` | A file called `promo.js` on any site. |
| `https://cdn.example.com/*` | Everything from that one host. |

There are two rules to remember:

- A pattern **without** `*` matches when the text appears anywhere in the address.
- A pattern **with** `*` must describe the whole address, from start to end. So start it with `*` unless you write the full `https://` part.

Upper and lower case are treated the same.

```bash
curl -G "https://curlshot.com/api/v1/screenshot" \
  --data-urlencode "access_key=YOUR_ACCESS_KEY" \
  --data-urlencode "url=https://github.com/microsoft/playwright" \
  --data-urlencode "block_requests=*.githubusercontent.com/*" \
  --output playwright-no-avatars.png
```

You get the repository page without the avatars and other images that GitHub serves from that host.

You can send up to 50 patterns. Separate them with commas, or repeat the option. Since the comma is the separator, a single pattern cannot contain one.

To find what to block, open the page in your browser, press F12 and look at the **Network** tab. It lists every request the page makes.

## Blocking is best-effort

These options catch the common cases. They do not catch everything, and it is better that you know this up front.

- The lists cover widely used ad, tracking, chat and consent services. A small or regional service may not be on them.
- A site can serve ads from its own address, where they look like normal content.
- A home-made cookie banner may have no button we recognise.
- When a banner is closed by pressing a button, the choice made is whichever button was found. If the capture must reflect a specific choice, set it up yourself with [`cookies`](https://curlshot.com/docs/options.md#cookies) or [`click`](https://curlshot.com/docs/customize.md).

When something slips through, hide it yourself. [`hide_selectors`](https://curlshot.com/docs/options.md#hide_selectors) removes any element you can point at with a CSS selector. A selector is a short pattern that names an element, such as `#promo-bar` for the element with the id `promo-bar`.

```bash
curl -G "https://curlshot.com/api/v1/screenshot" \
  --data-urlencode "access_key=YOUR_ACCESS_KEY" \
  --data-urlencode "url=https://en.wikipedia.org/wiki/Eiffel_Tower" \
  --data-urlencode "block_cookie_banners=true" \
  --data-urlencode "hide_selectors=#siteNotice,.vector-sticky-header" \
  --output eiffel-no-notices.png
```

The two work well together. Blocking handles the known cases across every site. `hide_selectors` handles the one stubborn element on the site you care about.

> **Common mistakes**
>
> - **A banner appears a moment after the page loads.** Add a short [`delay`](https://curlshot.com/docs/options.md#delay). The banner is hidden again after the wait.
> - **A wildcard pattern that never matches.** `ads/*` describes an address that starts with `ads/`, and none does. Write `*/ads/*`.
> - **A blank page after `block_resources=script`.** The site needs its JavaScript. Remove `script` from the list.
> - **An unknown type name.** A value outside the list returns [`invalid_options`](https://curlshot.com/docs/errors.md#invalid_options).
> - **Expecting the layout to close up.** Blocking an ad stops it from loading. The gap it leaves may remain. Hide the container with `hide_selectors`.

## Where to go next

- [Custom CSS, JavaScript and clicks](https://curlshot.com/docs/customize.md): hide, restyle and click things yourself.
- [Waiting and timing](https://curlshot.com/docs/waiting.md): give late pop-ups time to show up, so they can be removed.
- [Options reference](https://curlshot.com/docs/options.md#block_ads): the blocking options with their limits.
