# Manual blocking

Start with [automatic blocking](/runtime/automatic-blocking) and the non-async installation. Manual blocking gives explicit control over elements when automatic matching cannot cover them or when you deliberately choose async loading. Decide the required categories before changing markup.

## Scripts

Use the inert `fs-consent` type and declare required categories:

```html
<script type="fs-consent" fs-consent-categories="analytics" src="https://example.com/analytics.js"></script>
```

## Iframes

Move the URL from `src` to `fs-consent-src` so the browser cannot load it immediately:

```html
<iframe fs-consent-src="https://example.com/embed" fs-consent-categories="marketing" title="Example embed"></iframe>
```

Use this for an uncovered parent embed you control. You cannot edit elements inside a third-party iframe from the host page. A cookie-free embed may need gating even if the scan did not turn it into a saved tracker.

## Tracking images

An ordinary image `src` is not held by the automatic blocker. For images in your page, move it to the held-source attribute:

```html
<img fs-consent-src="https://example.com/pixel.gif" fs-consent-categories="marketing" alt="" />
```

See [Image trackers](/runtime/image-trackers) for detection and frame ownership considerations.

## Categories and verification

Supported categories are `essential`, `analytics`, `marketing` and `personalization`. Essential-only elements load without optional consent. A comma-separated list such as `analytics,marketing` requires both categories. These examples illustrate markup; choose categories from the resource's actual purpose and your consent requirements.

Keep the runtime installed. Test actual requests before a choice, after rejection, after each allowed category and after withdrawal. A placeholder or disappearing scan finding does not establish blocking. Withdrawal cannot undo data already sent; verify subsequent requests and reload behavior too.
