Description
n8n-nodes-data-profiler
An n8n community node that analyzes incoming data and produces a statistical profile of every field — types, null counts, unique counts, numeric stats, top string values and length distribution.
Think of it as a lightweight pandas.DataFrame.describe() for arbitrary JSON, available as a single drag-and-drop node in your workflow. Useful when you fetch a new API for the first time, when something downstream broke and you need to understand the shape of the data you actually got, or when you want quick data quality signals before loading into a database.
Why this exists
n8n shows you raw JSON in the right panel, which is great for one item but useless when you want to answer questions like:
- “How often is this field missing?”
- “Is
statusalways a string, or does it sometimes come back asnull?” - “What are the most common values for
country?” - “What’s the range of
priceacross all 5,000 items?”
This node answers all of them in one click.
Installation
In your n8n instance, go to Settings → Community Nodes → Install and enter:
n8n-nodes-data-profiler
For self-hosted n8n with manual installation:
npm install n8n-nodes-data-profiler
Usage
Drop the Data Profiler node after any node that produces structured data (HTTP Request, database query, Read CSV, etc.). That’s it — no credentials needed.
Modes
Parameters
| Parameter | Default | Description |
|—|—|—|
| Mode | Profile Array | How to group incoming items |
| Depth | 2 | How many levels deep to traverse nested objects |
| Sample Size | 3 | How many example values to include per field |
| Top Values Count | 5 | How many most frequent values to show for string fields |
Example
Input (5 items from some user API):
[
{ "id": 1, "name": "Alice", "country": "US", "age": 30, "tags": ["admin", "billing"] },
{ "id": 2, "name": "Bob", "country": "US", "age": null, "tags": ["billing"] },
{ "id": 3, "name": "Carol", "country": "DE", "age": 45, "tags": [] },
{ "id": 4, "name": "Dan", "country": "US", "age": 22, "tags": ["admin"] },
{ "id": 5, "name": "Eve", "country": "FR", "age": 38, "tags": ["admin", "ops", "billing"] }
]
Output (abbreviated):
{
"meta": {
"mode": "profileArray",
"totalItems": 5,
"fieldsFound": 5,
"profiledAt": "2026-05-15T13:22:00.000Z"
},
"profile": {
"age": {
"types": { "number": { "count": 4, "percent": 80 }, "null": { "count": 1, "percent": 20 } },
"count": 5, "nullCount": 1, "nullPercent": 20,
"uniqueCount": 4, "uniquePercent": 100,
"samples": [30, 45, 22],
"numeric": { "min": 22, "max": 45, "avg": 33.75, "median": 34 }
},
"country": {
"types": { "string": { "count": 5, "percent": 100 } },
"count": 5, "nullCount": 0, "nullPercent": 0,
"uniqueCount": 3, "uniquePercent": 60,
"samples": ["US", "US", "DE"],
"string": {
"minLength": 2, "maxLength": 2, "avgLength": 2,
"topValues": [
{ "value": "US", "count": 3, "percent": 60 },
{ "value": "DE", "count": 1, "percent": 20 },
{ "value": "FR", "count": 1, "percent": 20 }
]
}
},
"tags": {
"types": { "array": { "count": 5, "percent": 100 } },
"count": 5, "nullCount": 0, "nullPercent": 0,
"uniqueCount": 5, "uniquePercent": 100,
"samples": [["admin", "billing"], ["billing"], []],
"array": { "minLength": 0, "maxLength": 3, "avgLength": 1.6 }
}
}
}
You can then feed this into a Set, IF, or Code node to act on quality signals — e.g. “if email.nullPercent > 10, send a Slack alert”.
Common patterns
Quick data-quality gate before loading into a database:
HTTP Request → Data Profiler → IF (profile.email.nullPercent < 5) → Postgres Insert
Understand a new API:
HTTP Request → Data Profiler → Edit Fields (extract profile) → log to console / save to file
Compare two runs of the same dataset:
Two HTTP Request branches → each through Data Profiler → Merge → Diff via Code node