---
title: Text / Formatter
description: "Transform text: case, trim, pad, replace, split, slugify, extract, count, encode and decode"
---

Clean up, reshape, search or encode a piece of text, without writing code.

## What it does

You pick an **Operation** and point **Text** at your value, for example `{{ $input.title }}`. The node then does one thing to that text:

* **Change case**: *Uppercase*, *Lowercase*, *Title Case*, *camelCase*, *snake\_case*, *kebab-case*. The last three understand spaces, punctuation and existing camelCase, so `Order ID number` becomes `order_id_number`.
* **Shape**: *Trim* (remove spaces at both ends), *Pad*, *Replace*, *Split*, *Join*, *Slugify*, *Truncate*, *Default if empty*.
* **Find**: *Extract emails*, *Extract URLs*, *Extract numbers*, *Extract phone numbers* return every match, not just the first.
* **Count**: *Word count*, *Character count*. An emoji or accented letter counts as one character.
* **Encode** or **Decode** with a **Scheme**: *Base64*, *URL (whole URL)*, *URI component*, *HTML entities* or *Hex*. Accented letters and emoji survive a round trip.

*Slugify* turns `Héllo, Wörld!` into `hello-world`, which is handy for file names and links.

## When to use it

* Tidy scraped text before you save or send it: trim it, fix its case, or replace a placeholder.
* Pull every email address or link out of a page's text.
* Build a file name or link from a title with *Slugify*.
* Encode a value for a link with *URI component*, or decode Base64 text from an API.
* For patterns of your own and named fields, use [Regex](/nodes/builtin/datatransformation/regex/) instead.

## Inputs and settings

Every operation has **Operation** (default *Uppercase*) and **Text**. Some show extra settings:

| Operation | Extra settings |
| --- | --- |
| *Pad* | **Target Length** (default 0), **Pad With** (default a space), **Pad Side** (*Start* or *End*) |
| *Replace* | **Find**, **Replace With**, **Treat Find As Regex** (default off), **Regex Flags** (default `g`) |
| *Split* | **Separator** (default `,`). Empty splits into single characters. |
| *Join* | **Separator** (default `,`), placed between the joined entries |
| *Truncate* | **Maximum Length** (default 20), **Ellipsis** (default `…`), added only when the text is cut |
| *Default if empty* | **Default Value**, returned when the text is empty or only spaces |
| *Encode*, *Decode* | **Scheme** (default *Base64*) |

* *Replace* without regex replaces every occurrence of **Find**. With **Treat Find As Regex** on, the default `g` flag also replaces every match; add `i` (`gi`) to ignore case.
* *Join* expects **Text** to be a list, such as `{{ $input.tags }}`. A single text value comes back unchanged.
* *URL (whole URL)* leaves `:/?#&=` alone, so it is safe on a full address. *URI component* escapes them too; use it for one value inside a link.

## Outputs

The field depends on the operation:

* **`result`**: the new text for case, shaping, *Encode* and *Decode* operations. For *Split* it is a list.
* **`matches`**: the list of everything found by an *Extract* operation. It is an empty list when nothing matched.
* **`count`**: the number from *Word count* or *Character count*.

The output holds only that field. To keep the original data next to it, read it from the earlier node with an expression such as `{{ $('HTML Extract').title }}`.

## Dependencies and credentials

None. This node needs no connection and has no slots for other nodes.

## Example workflow

1. [Get Selected Text](/nodes/extension/getselectedtext/) with **Output field name** `selection` reads the text you highlighted on a page.
2. Text / Formatter with **Operation** *Extract emails* and **Text** `{{ $input.selection }}`. Every address comes back in `matches`.
3. A second Text / Formatter with **Operation** *Join*, **Text** `{{ $input.matches }}` and **Separator** `, ` gives one line of addresses in `result`.
4. A [Slack](/nodes/builtin/integration/slack/) node posts `{{ $input.result }}`.

## Common issues

* **"Invalid base64: could not decode the input as UTF-8 text."** The text is not Base64, or it is Base64 of a file rather than text. Check that you picked the right **Scheme**.
* **"Invalid hex: expected an even number of hex digits."** or **"Invalid hex: contains non-hexadecimal characters."** The text is not a clean hex string. Remove spaces or prefixes such as `0x`.
* **"Invalid URL encoding: malformed percent-escape sequence."** (or *Invalid URI component*). A `%` in the text is not followed by two hex digits. Check the text was really encoded.
* **Replace fails with an invalid regular expression error.** **Treat Find As Regex** is on and **Find** has a syntax error, or **Regex Flags** holds a letter that is not a flag. Turn the option off to replace plain text.
* **`matches` is empty.** Nothing in the text looks like an email, link, number or phone number. Phone numbers must be at least seven characters long and start and end with a digit; links must start with `http://` or `https://`.

## Related nodes

* [Regex](/nodes/builtin/datatransformation/regex/): your own patterns, with named groups as fields.
* [Edit Fields](/nodes/builtin/datatransformation/editfields/): put the result back next to the other fields.
* [Crypto](/nodes/builtin/datatransformation/crypto/): hashes and signatures rather than encodings.