In WordPress, escape every value at the moment you print it, using the function that matches the context: esc_html inside elements, esc_attr in attributes, esc_url for links, and wp_kses when you must keep some HTML. The handbook calls this escaping late.
Why escape at output
Cross-site scripting happens when untrusted text reaches a page as markup. The WordPress security guidance lists these principles: never trust user input, escape as late as possible, escape everything from untrusted sources including your own database, and never assume anything. It also says validation or rejection is better than sanitizing.
Pick the function by context
The escaping page gives this mapping:
esc_html(): Text inside an HTML element, strips HTMLesc_attr(): HTML attributes and most other outputesc_url(): All URLs, including src and hrefesc_url_raw(): URLs stored in the database or needed unencodedesc_js(): Inline JavaScriptesc_textarea(): Text inside a textareaesc_xml(): XML blockswp_kses(): Untrusted HTML that keeps markup, with an allowlist of tags and attributeswp_kses_post(): Shortcut for the HTML allowed in post content
An example
echo '<a href="' . esc_url( $link ) . '" title="' . esc_attr( $title ) . '">'
. esc_html( $label ) . '</a>';
Each value uses a different function because each sits in a different context.
Why late
The handbook gives reasons: code is easier to review, a variable cannot change between escaping and output, automated scanners can see it, and maintainers understand it faster. If you cannot escape late, for instance when output contains scripts that wp_kses() would strip, escape while building the string and name the variable with a suffix such as _escaped, _safe or _clean. Functions that cannot escape late should return safe HTML.
Common mistakes
- Escaping on input and printing raw later.
- Using
esc_htmlinside an attribute. - Echoing a database value because you wrote it yourself.
- Using
wp_kses_postwhereesc_htmlwould do.
Quick check
If I sanitized the value on save, do I still escape on output?
Yes. The guidance says to escape everything from untrusted sources, including the database, at output.
When do I use wp_kses instead of esc_html?
When users may legitimately include some HTML. Pass an allowlist of tags and attributes.
Sources
Last reviewed: 19 October 2026.