A Home Assistant custom integration to import and export long-term statistics from CSV, TSV, or JSON files.
Note: This integration provides actions only (no entities or dashboard cards). You call its actions from Developer Tools or automations.
- Installation | Importing | Mixed Import | Exporting | Inventory | Troubleshooting Tips
- Counter Statistics Explained | Delta Import | Inventory Categories
- Debug Logging Guide - How to enable debug logs for troubleshooting
This is the user guide. If you are a developer, check the Developer Documentation.
- Home Assistant 2026.1.0 or newer
- Download all files from
custom_components/import_statistics/in this repository - Copy them to
<config>/custom_components/import_statistics/(create folders if needed) - Add
import_statistics:to yourconfiguration.yaml - Restart Home Assistant
| Action | Description |
|---|---|
import_statistics.import_from_file |
Import statistics from a CSV/TSV file |
import_statistics.import_from_json |
Import statistics from JSON (UI or API) |
import_statistics.export_statistics |
Export statistics to CSV/TSV or JSON |
import_statistics.export_inventory |
Export metadata inventory of all statistics |
As this integration uses database-independent methods, it works with all databases supported by Home Assistant.
Import your statistics from CSV, TSV, or JSON files to populate or update Home Assistant's long-term statistics database.
- Copy your file to your Home Assistant config folder
- Go to Developer Tools → Actions
- Select
import_statistics: import_from_file(orimport_from_json) - Fill in the settings (from the UI or YAML)
- Click
perform actionto start the import.
filename(required)- Input file name (relative to Home Assistant config directory).
- Supported:
.csvor.tsvfor CSV/TSV import.jsonfor JSON import (useimport_from_jsonaction)
delimiter(optional)- Delimiter between columns for CSV/TSV import.
- If omitted, it is inferred from the filename extension:
.csvuses comma (,) by default.tsvuses tab (\t) by default
- Options:
\t(tab),;(semicolon),,(comma),|(pipe), or custom value.
decimal(required, default:".")- Decimal separator character:
"."for dot or","for comma.
- Decimal separator character:
datetime_format(optional, default:%d.%m.%Y %H:%M)- Input format of the
datetimestrings in the file. - Default:
DD.MM.YYYY HH:MM(e.g.,17.03.2024 02:00) - Common formats:
%d.%m.%Y %H:%M,%Y.%m.%d %H:%M,%Y-%m-%d %H:%M,%m/%d/%Y %H:%M,%d/%m/%Y %H:%M
- Input format of the
timezone_identifier(optional)- Defaults to Home Assistant's configured timezone if omitted. Typically can be left empty.
- Timezone identifier (check pytz timezones or https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
Important: Input files must contain a
unitcolumn with the unit of measurement for each statistic. For existing statistics, the unit in the input file must match the unit already stored in Home Assistant's database, otherwise the import will fail with an error.Note: Timestamps must be full hours (minutes must be
:00). Timestamps are interpreted in the specified timezone.Performance note: Importing large datasets may take time as the operation is synchronous. The action completes when all data is saved into the database.
action: import_statistics.import_from_file
data:
filename: my_statistics.tsv
delimiter: \t
decimal: "."action: import_statistics.import_from_file
data:
filename: my_statistics.csv
delimiter: ","
decimal: "."
datetime_format: "%Y-%m-%d %H:%M"
timezone_identifier: "Europe/Vienna"action: import_statistics.import_from_json
data:
statistics: <JSON content>Your file can contain one or both types of statistics:
- Measurements (state_class == measurement or measurement_angle) (temperature, humidity, direction, etc.): columns
min,max,mean - Counters (state_class == total or total_increasing) (energy, water meters, etc.): columns
sum,state(ordelta) - Mixed files: A single file can contain both measurement and counter rows (see Mixed Import below). However, delta cannot be mixed with measurements.
Before importing counters, make sure to read Understanding counter statistics in Home Assistant For importing counters, it is recommended to use the import with the delta column instead of importing sum/state, see Delta Import
Example files:
Only these columns are accepted (unknown columns cause an error):
| Column | Required | Description |
|---|---|---|
statistic_id |
Yes | The entity identifier |
start |
Yes | Timestamp |
unit |
Sometimes | Required for external statistics |
min, max, mean |
For measurements | Can coexist with counter columns in mixed files |
sum, state |
For counters | Can coexist with measurement columns in mixed files |
delta |
For counters | Alternative to sum/state; cannot be used in mixed files |
| Type | Format | Example | When to use |
|---|---|---|---|
| Internal | domain.name (with .) |
sensor.temperature |
For existing Home Assistant entities |
| External | domain:name (with :) |
sensor:imported_energy |
For external (custom/synthetic) statistics |
Internal statistics must match an existing entity.
- Encoding: UTF-8 (required for special characters like m³ or °C)
- Delimiter: Tab (default), comma, semicolon, or pipe
- Decimal separator:
.(default) or,
- Overwrites existing data: Importing the same timestamps replaces old values
- Gaps are preserved: Missing hours will show as gaps in graphs
- Synchronous operation: The action completes when all data is saved into the database. This can take a longer time for large input data
- Validation errors: Shown directly in the UI; check logs if import fails silently
If importing does not work and you do not get an error directly in the GUI, but there is an error in the Home Assistant logs, then this is a bug. This happens if the integration misses some checks, which lead to import errors later. Please create an issue.
The integration performs strict validation on all import data:
- All rows must be valid - If any row contains invalid data, the entire import fails
- Clear error messages - The error message will indicate which row failed and why
- No partial imports - Either all data is imported successfully, or none of it is
- Common validation errors:
- Invalid timestamp format or non-full-hour timestamps
- Invalid numeric values (non-numeric strings, NaN, empty values)
- Constraint violations (e.g., min > max for measurement data)
- Missing required columns
- Inconsistent units for the same
statistic_idacross rows in the import file
This strict validation ensures data integrity and helps you identify and fix data quality issues immediately.
You can also import via JSON, either through the UI or the Home Assistant API.
Example format: state_sum.json
Via API:
POST https://<your-ha-url>/api/services/import_statistics/import_from_json
Content-Type: application/json
<JSON content>Since v5.1.0, a single file can contain both measurement and counter statistics. This is useful when you want to import data for different types of sensors in one operation.
- Each
statistic_idmust be consistently one type — a single entity cannot have measurement values in some rows and counter values in others - Measurement rows provide
min,max,meanand leavesum/stateempty - Counter rows provide
sum/stateand leavemin/max/meanempty - The
deltacolumn cannot be used in mixed files — delta files must contain only delta data - No new service parameters are needed; the same
import_from_fileandimport_from_jsonactions work as before
statistic_id start unit mean min max sum state
sensor.temperature 01.01.2024 00:00 °C 20.5 18.0 23.0
sensor.temperature 01.01.2024 01:00 °C 21.0 19.0 24.0
sensor.energy 01.01.2024 00:00 kWh 100.5 100.5
sensor.energy 01.01.2024 01:00 kWh 105.2 105.2Measurement rows (
sensor.temperature) have values inmean/min/maxwith emptysum/state. Counter rows (sensor.energy) have values insum/statewith emptymean/min/max.
[
{
"statistic_id": "sensor.temperature",
"unit": "°C",
"values": [
{"start": "01.01.2024 00:00", "mean": 20.5, "min": 18.0, "max": 23.0},
{"start": "01.01.2024 01:00", "mean": 21.0, "min": 19.0, "max": 24.0}
]
},
{
"statistic_id": "sensor.energy",
"unit": "kWh",
"values": [
{"start": "01.01.2024 00:00", "sum": 100.5, "state": 100.5},
{"start": "01.01.2024 01:00", "sum": 105.2, "state": 105.2}
]
}
]In JSON format, each entity object specifies its own fields — sensor entities use
mean/min/max, counter entities usesum/state.
Export your statistics to a file e.g. for backup, analysis, preparing a counter import with delta, or transfer to another Home Assistant instance.
- Go to Developer Tools → Actions
- Select
import_statistics: export_statistics - Fill in the settings (from the UI or YAML)
- Click
perform actionto start the export.
filename(required)- Output file name (relative to Home Assistant config directory).
- Supported:
.jsonfor JSON export.csvor.tsvfor TSV/CSV export
entities(optional)- List of statistic IDs or entity IDs to export. Make sure to use a YAML list with
- - Leave empty to export all available statistics.
- Supports wildcard patterns using
*(glob matching) inside an entry:sensor.paris_*(prefix)sensor.*_temperature(suffix)sensor.*temp*(contains)
- Constraints:
*alone is not allowed- Broad patterns like
sensor.*/sensor:*must not be mixed with other entries (omitentitiesto export all)
- List of statistic IDs or entity IDs to export. Make sure to use a YAML list with
start_time(optional)- Start of the export range format:
%Y-%m-%d %H:%M:%S(YYYY-MM-DD HH:MM:SS). Make sure you use quotes around the string. - Must be a full hour (
MM:SSmust be00:00). - If omitted, export starts from the earliest available long-term (hourly) statistic.
- Start of the export range format:
end_time(optional)- End of the export range format:
%Y-%m-%d %H:%M:%S(YYYY-MM-DD HH:MM:SS). Make sure you use quotes around the string. - Must be a full hour (
MM:SSmust be00:00). - If omitted, export ends at the most recent available long-term (hourly) statistic.
- End of the export range format:
timezone_identifier(optional)- Defaults to Home Assistant's configured timezone if omitted. Typically can be left empty.
- Timezone identifier (check pytz timezones or https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
datetime_format(optional, default:%d.%m.%Y %H:%M)- Output format of the
datetimestrings in the exported file.
- Output format of the
delimiter(optional)- Delimiter between columns for TSV/CSV export.
- If omitted, it is inferred from the filename extension:
.csvuses comma (,) by default.tsvuses tab (\t) by default
decimal(required, default:".")- Decimal separator character:
"."for dot or","for comma.
- Decimal separator character:
split_by(optional, default:none)- Split output into multiple files by statistic type:
none: default; write a single combined filemeasurement: write only measurements statistics (mean/min/max)counter: write only counter statistics (sum/state/delta)both: write both files
- Output files use suffixes
_measurementsand_countersbefore the extension.
- Split output into multiple files by statistic type:
counter_fields(optional, default:both)- Controls which counter columns are written in CSV/TSV exports:
both: includestate,sum, anddeltasum: includestateandsumdelta: includedeltaonly
- Limitation: this option is ignored for JSON export.
- Controls which counter columns are written in CSV/TSV exports:
Note: If you omit
start_time/end_time, the action will auto-detect the time range from the recorder. This requires long-term (hourly) statistics to exist. On new Home Assistant instances you may only have short-term statistics at first; in that case, wait until long-term statistics are generated, or provide explicitstart_timeandend_time.Performance note: Exporting all statistics from large databases (450k+ records) may take 30-60 seconds depending on hardware.
action: import_statistics.export_statistics
data:
filename: exported_statistics.tsv
entities:
- sensor.temperature
- sensor.energy_consumption
- sensor:ext_value
start_time: "2025-12-22 12:00:00"
end_time: "2025-12-25 12:00:00"
delimiter: \t
decimal: "."
# timezone_identifier: Europe/Vienna # Optional - defaults to HA timezoneaction: import_statistics.export_statistics
data:
filename: temperatures.tsv
entities:
- sensor.*_temperature
start_time: "2025-12-22 00:00:00"
end_time: "2025-12-23 00:00:00"
delimiter: \t
decimal: "."action: import_statistics.export_statistics
data:
filename: exported_statistics.tsv
delimiter: \t
decimal: "."action: import_statistics.export_statistics
data:
filename: exported_statistics.tsv
split_by: both
delimiter: \t
decimal: "."action: import_statistics.export_statistics
data:
filename: exported_statistics.tsv
entities:
- sensor.temperature
- sensor.energy_consumption
start_time: "2025-12-22 00:00:00"
end_time: "2025-12-23 00:00:00"
split_by: measurements
delimiter: \t
decimal: "."The exported file contains:
| For Measurements | For Counters |
|---|---|
min, max, mean |
sum, state, delta |
Note: You can export measurements and counters together. The exported file can be re-imported directly as long as the delta-column is not exported — mixed files with both measurement and counter data are supported since v5.1.0.
Export a metadata-only inventory of all long-term statistics. This is useful for:
- Migration planning: Compare statistics between old and new Home Assistant instances
- Database analysis: Understand what statistics exist and their sizes
- Cleanup: Identify deleted or orphaned statistics
- Go to Developer Tools → Actions
- Select
import_statistics: export_inventory - Fill in the settings (from the UI or YAML)
- Click
perform actionto start the export.
filename(required)- Output file name (relative to Home Assistant config directory).
- Use
.tsvor.csvextension.
delimiter(optional)- Delimiter between columns.
- If omitted, it is inferred from the filename extension:
.csvuses comma (,) by default.tsvuses tab (\t) by default
timezone_identifier(optional)- Defaults to Home Assistant's configured timezone if omitted.
- Used for formatting
first_seenandlast_seentimestamps.
action: import_statistics.export_inventory
data:
filename: statistics_inventory.csv-
Export creates two files using the same base name:
<filename>.csvor<filename>.tsv: table only (one row per statistic, no summary block)<filename>.txt: summary only
-
Example: if
filename: inventory.csv, outputs are:inventory.csv(table)inventory.txt(summary)
-
Summary file content:
Total statistics: 257
Measurements: 194
Counters: 63
Total samples: 5038317
Global start: 2022-01-09 16:00:00
Global end: 2026-02-12 13:00:00
Active statistics: 224
Orphan statistics: 7
Deleted statistics: 26
External statistics: 0
- Table file content (one row per statistic):
| statistic_id | unit_of_measurement | source | category | type | samples_count | first_seen | last_seen | days_span |
|---|---|---|---|---|---|---|---|---|
| sensor.button_master_power | % | recorder | Active | Measurement | 32949 | 2/12/2022 10:00 | 2/12/2026 13:00 | 1461.1 |
| sensor.disk_free | GiB | recorder | Active | Measurement | 35876 | 1/9/2022 16:00 | 2/12/2026 13:00 | 1494.9 |
| sensor.disk_use | GiB | recorder | Active | Measurement | 35876 | 1/9/2022 16:00 | 2/12/2026 13:00 | 1494.9 |
| sensor.disk_use_percent | % | recorder | Active | Measurement | 35876 | 1/9/2022 16:00 | 2/12/2026 13:00 | 1494.9 |
| sensor.e3_tcu10_x07_buffer_main_temperature | °C | recorder | Active | Measurement | 20326 | 9/29/2023 10:00 | 2/12/2026 13:00 | 867.2 |
| sensor.e3_tcu10_x07_compressor_hours | h | recorder | Active | Counter | 17638 | 1/20/2024 21:00 | 2/12/2026 13:00 | 753.7 |
| sensor.e3_tcu10_x07_compressor_starts | recorder | Active | Counter | 17638 | 1/20/2024 21:00 | 2/12/2026 13:00 | 753.7 |
| Column | Description |
|---|---|
statistic_id |
The statistic ID (e.g., sensor.temperature) |
unit_of_measurement |
Unit (e.g., °C, kWh) |
source |
Source of the statistic (e.g., recorder) |
category |
Classification: Active, Orphan, Deleted, or External |
type |
Measurement (has mean/min/max) or Counter (has sum) |
samples_count |
Number of long-term (hourly) samples |
first_seen |
Timestamp of earliest sample |
last_seen |
Timestamp of most recent sample |
days_span |
Number of days covered by samples |
Category classification is based on the Home Assistant entity registry and does not use states_meta.
- Active:
statistic_idexists in the entity registry active entities (core.entity_registry.entities). - Orphan:
statistic_idexists in the entity registry deleted entities (core.entity_registry.deleted_entities) and has a non-nullorphaned_timestamp. - Deleted:
statistic_idexists incore.entity_registry.deleted_entitiesand has a null/missingorphaned_timestamp, orstatistic_idis not found in the entity registry at all (neither active nor deleted).
- External: Statistic is external (either
source != "recorder"orstatistic_iduses thedomain:nameformat with:).
For more details, see Export Inventory Categories.
- Import
delta, notsumandstate - Export first
- Modify the exported file
- Import
See Delta Import
- Always make a backup before importing
- Consider using the export functionality for backup as well
- Test with a small dataset first (10-20 rows)
- Create a test entity for initial imports
- Verify data in History graph before checking Energy Dashboard
- Enable debug logging to see detailed error messages (see Debug Logging Guide)
- Existing values can be overwritten - use this to correct mistakes
- Use Excel, Google Sheets or similar to prepare the data
- Verify column headers match exactly
- Check for consistent data types in each column
- Check for consistent usage of delimiters
- Validate timestamps are full hours
For troubleshooting tips, see Troubleshooting Tips for Import Statistics Integration.
- Community Guide: Loading, Manipulating, and Recovering Statistics — Detailed examples for fixing historical data (thanks to Geoffrey!)
- Jeedom Migration Guide — How to import statistics from Jeedom

