> ## Documentation Index
> Fetch the complete documentation index at: https://docs.datafog.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# US routing numbers

> Context-required US_ROUTING_NUMBER detection and transformation boundaries

<Note>This detector is available in Core 0.4.0 or newer.</Note>

`US_ROUTING_NUMBER` is enabled by default in every locale. It detects exactly 9 contiguous ASCII digits immediately after `routing`, `Routing Number`, `ABA`, `ABA Routing Number` (ASCII case insensitive). Words within a label require one or more horizontal spaces. Horizontal spacing means space, tab, nonbreaking space, or narrow nonbreaking space. Between label and value, any number of horizontal spaces and at most one colon, hash, or hyphen are accepted. Newlines and intervening prose are rejected. ASCII letters or digits immediately adjacent to the label or value prevent a match, including labels joined directly to digits.

Only the digits are included in the finding and replacement span; the label remains. Bare numbers and structured field names do not provide context. Each string leaf is scanned independently.

This is lexical detection, not identifier validation: checksums, assigned prefixes, and active directory status are not checked. Invalid check digits and transcription errors remain detectable. See the [official specification](https://www.aba.com/news-research/analysis-guides/routing-number-policy-procedures).

```python theme={null}
from datafog_core import scan_and_transform
result = scan_and_transform(
    "routing: 021000021",
    {"transform": {"default": {"strategy": "redact"}, "entities": ["US_ROUTING_NUMBER"]}},
)
assert result.text == "routing: [US_ROUTING_NUMBER]"
```

```rust theme={null}
use datafog_core::{scan, TransformationConfig, TransformationStrategy, transform};
let text = "routing: 021000021";
let config = TransformationConfig::new(TransformationStrategy::Redact)
    .with_entities(vec!["US_ROUTING_NUMBER".to_owned()]).unwrap();
assert_eq!(transform(text, &scan(text), &config).unwrap().text,
           "routing: [US_ROUTING_NUMBER]");
```

```javascript theme={null}
// Node: import from "@datafog/node".
// Browser: import from "@datafog/wasm" and await init() first.
import { scanAndTransform } from "@datafog/node";
const result = scanAndTransform("routing: 021000021", {
  transform: { default: { strategy: "redact" }, entities: ["US_ROUTING_NUMBER"] },
});
console.assert(result.text === "routing: [US_ROUTING_NUMBER]");
```

Structured scanning uses the same configuration with `scan_and_transform_structured` (Python), `scanAndTransformStructured` (Node/WASM), or `structured::scan_and_transform` (Rust). A leaf containing `"routing: 021000021"` is detected; an object such as `{"US_ROUTING_NUMBER": "021000021"}` is not classified from its key.

Rust, Python, Node, and WASM use the same core detector and shared fixtures. Findings expose `datafog-core/us-routing-number` provenance, package version, and no confidence score. Byte and code-point offsets remain relative to the original string; JavaScript additionally exposes UTF-16 offsets. Existing generic findings may overlap these digits; use the entity allowlist above to select this detector for transformations. Redact, remove, mask, and native provider-backed pseudonymization/tokenization use the same value span. WASM retains its existing provider limitations.
