Skip to main content

Squillify development is paused indefinitely. Read why, and discover what this experiment achieved. Read the story

MicroSkills Reference

Sanitize HTML

web.sanitize_html

ProductionEngine wrapper (Class A)Deterministicstrictfastv1.0.0
File inputNo network

Overview

You send HTML and we rebuild it from an allowlist, so anything not explicitly permitted disappears: script and style elements, iframes, forms, on-event handlers, and links using a scheme outside ftp, http, https, and mailto. Four ready-made policies run from plain text through to tables and headings, or you can name your own tags and attributes — a list of your own can narrow what survives but never re-admit active markup. Surviving anchors can be given target and rel attributes for you. The cleaned markup comes back as sanitizedHtml, so nothing overwrites what you sent. Accepts file input via file_ref — no need to extract file content first.

Markup you did not write can carry an attack, and an allowlist that only keeps what it recognises is far safer than a blocklist that tries to name every trick.

Reliability

Same markup and same policy always give the same result, and nothing leaves the platform. Four behaviours matter before you rely on this. Under every policy, your own included, an anchor may only use ftp, http, https, or mailto, and an image only http or https, so a javascript: or data: link loses its href while the element itself stays; because we clean without a base address, a relative href like "/pricing" and a fragment href like "#top" are dropped the same way, so resolve links before cleaning if you need them. A custom policy can only narrow what survives, never widen it: asking for an active element such as script or iframe, for an on-event handler, or for style, srcdoc or formaction is refused as invalid input, so the answer is never markup you believed was screened but was not. The counts under removed are before-and-after differences rather than an audit trail, and unsafeUrls is a plain text scan, so it also counts the word "data:" in ordinary prose. Bad input is rejected outright and retrying will not help — sending neither html nor file_ref, an unrecognised policy, policy "custom" with no customPolicy object or one that asks for a refused element or attribute, a file reference we cannot read for you, or content beyond 2097152 bytes.

Context footprint

The reply is roughly the size of your markup, or smaller once the unwanted parts are gone, plus three counts. A successful call costs 1 execution credit.

When to use it

Before you display or store HTML that came from a person, a scraper, or a model.

When scripts, forms, or javascript: links have to survive, or when you only want the markup smaller rather than safer.

Runs on jsoup's allowlist sanitizer, the long-standing Java answer to this job.

Scope

Note
We rebuild HTML from an allowlist so what comes back is safe to put on a page.

Non-goals

  • Does not render the markup or run anything in it
  • Does not fetch images, stylesheets, or any other linked resource
  • Does not keep scripts, styles, forms, or inline event handlers
  • Does not resolve relative links, which lose their href instead

Properties

IdempotentRetry safeStreaming supportedFile input supportedRequires external service

Capabilities

normalizationparsing

Cost & billing

Flat rate per invocation

MetercallsBillable onsuccessCost per call1 credit

File handling

Accepts file_refProduces file_refMax input2 MBMax file size2 MB

File limits

Constraints this skill applies to your input and generated files. The “Limited by” column shows the static source of each cap; none of these can be raised by upgrading your plan.

LimitValueLimited by
Maximum size per input file2 MiBSkill maximum

How we handle your data

Sensitive output possible
What this means

This skill may receive sensitive content and may return submitted, transformed, extracted, or reformatted content.

Squillify guarantees
  • Runs inside Squillify
  • This skill runs inside Squillify.
  • Payloads are not sent to an external service by this skill.
  • Squillify does not permanently store submitted payloads.
  • Telemetry records metadata only, not submitted content.
  • Submitted payloads are not used for training.
  • Submitted payloads are not reviewed by humans.
  • This skill does not target sensitive data.
  • The response may contain submitted or transformed content.
Your responsibility

Squillify does not determine whether submitted content is sensitive. Your application is responsible for deciding what data it is allowed to submit. Your application is responsible for securing the response.

Read the Microskill Data Handling Policy

Input schema

FieldTypeRequiredDescription
htmlstringNoBounded inline source. Required unless file_ref is provided.
file_refstringNoTenant-scoped opaque file reference. Omit it when inline source is supplied.
policystringNoSanitization policy; omit it for basic_formatting.
customPolicyobjectNoPurpose-bound custom sanitizer policy object; omit it unless policy is custom. It contains from 0 through 256 purpose-bound properties — unconstrained RFC 8259 JSON items.
rewriteLinksbooleanNoWhether unsafe link targets are rewritten; omit it for true.
addNoopenerbooleanNoWhether external links receive noopener; omit it for true.

Output schema

FieldTypeRequiredDescription
okbooleanYesWhether sanitization completed successfully.
sanitizedHtmlstringYesSanitized HTML with active content removed.
removedobjectYesClosed removal-count receipt for elements, attributes, URLs, and comments. Its documented web receipt properties are bounded to 128 entries — unconstrained RFC 8259 JSON items.
warningsarrayNoBounded array of non-fatal safe warning strings. The item shape is defined by the nested schema and the array contains from 0 through 20000 items.
metadataobjectYesClosed sanitizer metadata receipt with applied policy and transformation counts. Its documented web receipt properties are bounded to 128 entries — unconstrained RFC 8259 JSON items.

API contract

POST /v1/execute
curl
curl -sS -X POST "$BASE/v1/execute" -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' -d '{"skillKey":"web.sanitize_html","input":{"html":"<p onclick=\"steal()\">Welcome</p>"}}'
Integrations
TypeScript SDK
import { Squillify } from "@squillify/sdk";

const sq = new Squillify({ apiKey: process.env.SQUILLIFY_API_KEY });

const { output } = await sq.execute("web.sanitize_html", {"html":"<p onclick=\"steal()\">Welcome<script>alert(1)</script></p>"});

Errors

CodeHTTPRetryableDescription
VALIDATION_ERROR400NoThe request payload failed schema validation.
UNAUTHORIZED401NoMissing or invalid API key.
SKILL_NOT_ACCESSIBLE403NoThe API key is not granted access to this skill.
SKILL_NOT_AVAILABLE_FOR_PLAN403NoThis skill is not included in your current plan.
PLAN_ELIGIBILITY_UNAVAILABLE503YesPlan eligibility could not be decided. Retry after backoff.
SKILL_NOT_FOUND404NoThe requested skill or version does not exist.
TENANT_RATE_LIMITED429YesRequest rate limit exceeded. Retry after backoff.
QUOTA_EXCEEDED429YesPlan quota exhausted. Retryable once the quota period resets.
EXECUTION_TIMEOUT504YesExecution exceeded the allowed time budget.

Other limits

LimitValue
Recommended inline bytes32 KiB

Limitations

  • Does not render the markup or run anything in it
  • Does not fetch images, stylesheets, or any other linked resource
  • Does not keep scripts, styles, forms, or inline event handlers
  • Does not resolve relative links, which lose their href instead
  • Keeping scripts, forms, or anything else that has to stay active
  • Shrinking markup for transfer, which web.minify_html does

How to call

POST /v1/execute (requires authentication)

Request bodyjson
{
  "skillKey": "web.sanitize_html",
  "input": {
    "html": "<p onclick=\"steal()\">Welcome<script>alert(1)</script></p>"
  }
}

Examples

Script and inline handler removed

Inputjson
{
  "html": "<p onclick=\"steal()\">Welcome<script>alert(1)</script></p>"
}
Expected outputjson
{
  "ok": true,
  "sanitizedHtml": "<p>Welcome</p>",
  "metadata": {
    "policy": "basic_formatting"
  },
  "removed": {
    "elements": 1,
    "attributes": 1,
    "unsafeUrls": 0
  }
}

plain_text policy leaves only the words

Inputjson
{
  "policy": "plain_text",
  "html": "<p><b>Welcome</b> aboard</p>"
}
Expected outputjson
{
  "ok": true,
  "sanitizedHtml": "Welcome aboard",
  "metadata": {
    "policy": "plain_text"
  },
  "removed": {
    "elements": 2,
    "attributes": 0,
    "unsafeUrls": 0
  }
}
  • Clean HTML from a person, a scraper, or a model before you show it
  • Strip scripts and onclick handlers out of rich-text submissions
  • Reduce markup to its visible text with the plain_text policy

Avoid for

  • Keeping scripts, forms, or anything else that has to stay active
  • Shrinking markup for transfer, which web.minify_html does

Composable with

Safety & privacy

  • Runs without calling any external service.
  • Your payloads are never stored permanently.
  • Telemetry captures metadata only — never your payload contents.
  • We never train models on your payloads.
  • No human reviews your payloads.

Tags

sanitizationsecurityweb