Home Assistant without HACS: the built-in InfluxDB integration
The way we recommend from Home Assistant is the Tag Historian integration, installed through HACS: you pick entities in a dialog with your tag quota in view, it sends each entity's unit, imports the history the recorder already holds and follows an entity you rename. This page is the way without HACS.
Home Assistant's built-in influxdb integration can send history straight to Tag Historian — nothing to install. The connection is a dialog under Settings → Devices & services; the entity filter is a short block of configuration.yaml, because Home Assistant has no screen for it yet.
This page is the setup, and then the four settings that decide whether it works. Before any of it: read whether you need external storage at all. For a lot of people the honest answer is no, and that page says so.
Last updated
What this actually does
Tag Historian speaks the InfluxDB v2 write protocol, which is exactly what Home Assistant's integration produces when you set it up as InfluxDB v2.x / v3. So Home Assistant thinks it is writing to an InfluxDB, and the data lands in an account in Azure Sweden Central instead of on the machine in your cupboard.
Numeric state is stored at full resolution for 14 days on Free, 1 year on Pro and 2 years on Business. After that window the individual readings are deleted and the hourly minimum, maximum, average and count stay for 10 years — on every plan, including the free one. See how long data is kept.
1. Get an API key
Create an account and an API key first. The free plan is €0 and takes an email address — no card — and gives you 5 tags and 50,000 readings a day. Then create the key on the Settings page in Tag Historian Explorer — and the scope you give it is not a detail.
The key is shown once. Copy it straight into the API token field when you add the integration in step 3 — if you lose it, generate a new one rather than hunting for the old one.
2. Write the entity filter into configuration.yaml
The connection is set up in the UI, but the integration still reads its entity filter and its retry count from configuration.yaml only — Home Assistant 2026.10 has no screen for either. Add this block before the connection exists, so the very first write is already filtered:
influxdb:
# The connection is set up in the UI (step 3) - no host, token,
# organization or bucket in this block.
max_retries: 3
precision: s
include:
entities:
- sensor.outdoor_temperature
- sensor.indoor_temperature
- sensor.energy_consumption
- binary_sensor.heat_pump_runningNo restart needed. The integration reads this block when it starts, and it starts in the next step. Keep the address and the key out of it: host, token, organization and bucket in this block are the old YAML connection, which Home Assistant is removing (more below).
3. Add the integration
- Settings → Devices & services → Add integration, search for InfluxDB and pick it. If Home Assistant answers with This integration allows only one configuration instead, it already has an InfluxDB connection — see below.
- Choose InfluxDB v2.x / v3, not v1.x — Tag Historian speaks the v2 write API.
- Fill in the form and press Submit:
| Field | Enter |
|---|---|
| URL | https://api.taghistorian.com — the form starts you off with https://: keep it, type the host after it, and nothing more. Home Assistant adds /api/v2/write itself. |
| Verify SSL certificate | On. The form starts with it off. The endpoint has an ordinary public certificate, so there is no reason to skip checking it. |
| Organization | Anything, for example home. Home Assistant requires it; Tag Historian ignores it. |
| Bucket | Anything, for example home — same reason. Your API key alone decides where the data lands. |
| API token | The Write key from step 1. |
| SSL CA certificate (Optional) | Leave empty. |
Home Assistant test-writes to the endpoint before it saves anything, so a wrong value is caught in the dialog rather than a week later. The finished entry is called home (https://api.taghistorian.com) — Home Assistant names it after the bucket and the URL. Readings appear as sensor.outdoor_temperature and so on within a minute or two. If the dialog stops instead:
- Invalid organization, bucket or token — the test write was refused, and never because of the organization or the bucket: Tag Historian does not look at either. The key is wrong or revoked (
401), it is a Read key (403), or the URL has a path after the host (404). - The same message when the URL starts with
http://, or has lost itshttps://. Plain HTTP is answered with a redirect to HTTPS, and Home Assistant does not follow it. The key went over the network unencrypted on that attempt, so revoke it in Tag Historian and create a new one. - The same message again when the account is refusing writes for now: an email address still unconfirmed after the 7-day grace period (
403), or the daily readings quota or the storage quota used up (429,402). The test write goes through the same checks as a real one. - Failed to connect — the host is mistyped,
https://is in the field twice (a full URL pasted after the one the form started with), or Home Assistant cannot reach the internet.
The four settings that matter
The first two live in the configuration.yaml block from step 2 — there is no screen for them. The last two are how Home Assistant shapes what it sends, wherever the connection was set up. To change the block later, edit it and restart Home Assistant, or reload the integration (Settings → Devices & services → InfluxDB → ⋮ → Reload), which reads it again.
1. include.entities — or Home Assistant sends everything
By default the integration ships every state change of every entity — every sensor, every automation toggle, every device tracker. Each distinct entity becomes one Tag Historian tag, and the free plan includes 5. An unfiltered Home Assistant burns through that in the first second, and every entity past the quota is refused with 422. Tags that already exist keep writing. That is why the filter goes in before the connection does: the integration starts sending the moment the dialog closes.
So filter at the source. The integration supports domains, entities and globs:
include:
domains: [sensor] # every sensor - usually far more than you want
entity_globs: ["sensor.*_temperature"]
entities: [binary_sensor.heat_pump_running]An entity listed under include.entities always wins over any exclude rule. The safest shape is the one in step 2: an explicit list of exactly the entities you want history for, and nothing else.
2. max_retries: 3 — because the default is 0
Home Assistant's default is no retries, and it never reads the Retry-After header. With the default, a batch that meets a daily quota (429) or a brief interruption (503) is thrown away and the run moves on — that data is gone. max_retries: 3 makes the integration re-attempt on its own schedule, which rides out short interruptions in practice. It still cannot wait out a daily quota: data sent while hard over quota is dropped by Home Assistant once its retries run out.
3. A numeric entity costs one tag. A non-numeric one costs several
Home Assistant sends the entity's state and every one of its attributes on the same line. What that costs depends on the state. If the state is a number — or one of the on/off pairs Home Assistant converts, like on/off and home/not_home — it arrives in the line's value field, Tag Historian stores that, takes the entity's friendly name as the tag's description and ignores every other attribute beside it. One entity, one tag: sensor.outdoor_temperature. That is the normal case and it is what the include list above is made of. The unit is the one thing to set by hand, once, on the tag's page in Tag Historian Explorer: this integration sends it as the line's measurement name, which other settings of the integration fill with something else, so it is not read from there. The custom component sends it along.
If the state is not a number — a climate entity sitting at heat, a weather entity at cloudy — there is no value field on that line, so every numeric attribute becomes its own tag instead, named {entity}.{attribute}. A single climate.living_room produces climate.living_room.current_temperature, climate.living_room.temperature, climate.living_room.min_temp, climate.living_room.max_temp and more — several tags from one line in your include list, most of them constants that never change.
So keep include.entities to entities whose state is a number. If you want one attribute of a non-numeric entity, create a template sensor that exposes it as its own entity: one tag with a name you chose, instead of six you did not.
One more thing about naming: leave out a static tags: block — another YAML-only option. Extra tags get appended to the series name, so sensor.outdoor_temperature becomes sensor.outdoor_temperature.instance-home2. That is useful on purpose — two Home Assistant instances writing the same entity stay two distinct series — but it is a surprise if you did not mean it.
4. unknown and unavailable never arrive
Home Assistant does not send non-numeric states, so a sensor that goes unavailable simply stops producing points. A gap in the chart means “Home Assistant had nothing numeric to say”, not that zeroes were stored. That matches how Tag Historian treats data everywhere: a missing reading is a gap, never an invented zero.
Reading the log
| Status | What it means |
|---|---|
204 | Everything was accepted. |
400 | An unparsable body or an invalid precision. The connection test gets one too, on purpose — see above — but Home Assistant never logs that one. |
401 | Wrong or revoked API key. In the setup dialog this reads Invalid organization, bucket or token. |
403 | A Read-scope key — writing needs Write. Or: email address not confirmed and the 7-day grace period has passed. Reading still works; confirm the address and writing resumes immediately. |
422 | New entities would exceed your tag quota, so those points were dropped. Existing tags were still written. |
429 | Daily readings quota reached. Retry-After says when to come back. |
503 | Temporarily unavailable, with Retry-After — never a silent drop. |
The full table, including the storage-quota and payload-size cases, is on the line protocol reference.
Already sending to an InfluxDB of your own?
Home Assistant holds exactly one InfluxDB connection. Pick InfluxDB under Add integration while one exists and you get no form, only This integration allows only one configuration: “InfluxDB supports only one configuration. Adding additional ones is not needed.” So it is one or the other:
- Move the connection to Tag Historian. If yours is InfluxDB 2.x or 3: Settings → Devices & services → InfluxDB → ⋮ → Reconfigure, and enter the values from step 3 — the same connection test runs. If it is InfluxDB 1.x, Reconfigure only offers the 1.x fields (database, username, password), so delete the entry and add a new one, choosing v2.x / v3. Do the same if your InfluxDB used a certificate file of its own in SSL CA certificate: Reconfigure keeps that file and has no way to clear it, so the test fails with SSL certificate error against Tag Historian's ordinary public certificate. Either way, the filter you already have in
configuration.yamlnow decides what reaches Tag Historian — narrow it to what you would spend tags on before you switch. - Keep your InfluxDB and add Tag Historian beside it. The built-in integration cannot do both. The HACS component can, because it is a separate integration with its own connection and its own entity picker.
The same goes if you ever remove the InfluxDB entry for good — to move to the HACS component, say. Remove the influxdb: block from configuration.yaml as well. A block with no entry beside it is read as an old-style connection at every restart, and every restart puts Failed to import InfluxDB YAML configuration back in Repairs.
Set up from the old version of this page?
This page used to put the whole connection in configuration.yaml: api_version, host, port, ssl, token, organization and bucket. Home Assistant has marked those keys for removal. Release 2026.10 still reads them, imports them into an InfluxDB entry under Devices & services, and raises a Repairs card called The InfluxDB YAML configuration is being removed. The card names 2026.9.0 as the release they break in, which has already passed, so the removal can land in any release.
Nothing needs entering again. Delete those seven lines, keep precision, max_retries and include, and restart: the card goes away and the imported connection keeps writing. The taghistorian_api_key line in secrets.yaml can go too — the key is stored with the integration now.
How many tags will you actually need?
The arithmetic nobody publishes: a tag is a series, not a reading. A sensor polled every ten seconds and a sensor polled once an hour cost the same, because the price follows the number of series and not the sample rate. What that means per plan:
| Plan | Entities | Readings/day | That is roughly |
|---|---|---|---|
| Free | 5 | 50,000 | 5 entities, each once every 10 seconds, all day |
| Pro | 50 | 500,000 | 50 entities, each once every ~8.6 seconds |
| Business | 500 | 5,000,000 | 500 entities, each once every ~8.6 seconds |
The daily allowance is a shared budget rather than a per-tag rate, so you can spend it on breadth or on frequency: Pro's 500,000 is 50 entities at ~8.6 seconds, or 10 entities at ~1.7 seconds.
Renaming an entity
A tag is named after its entity's id, and include.entities lists ids. Rename an entity in Home Assistant and it is no longer on the list, so its readings stop. Put the new id on the list and they start again — as a new tag, with the history left behind under the old name.
To keep one history, rename the tag before you change the list: in Tag Historian Explorer, Tags, open the tag, Rename, and give it the entity's new id. Nothing is copied — the readings from before read under the new name — and the old id stays on as a former name, so anything still sent under it lands in the same tag. If readings under the new id have already started a tag of their own, open the old one and use Merge into… instead: the two become one history, and only one of them counts against your plan. The custom component follows renames by itself.
What this is not
- It is not a replacement for the recorder. Home Assistant still keeps its own database and still draws its own charts from it. This is a copy that outlives the box.
- It does not read back into Home Assistant. There is no query API and no Flux — data comes out through the Tag Historian API, its charts, and exports to CSV, JSON or Parquet.
- Strings are not stored. Only numbers, and booleans as 1 and 0.
- It does not bring the history you already have. The built-in integration sends from the moment it is set up. The days the recorder already holds can be imported with their original timestamps — outside your daily reading allowance, within your plan's full-resolution window and an import allowance of its daily readings times that window — by the HACS integration, which forwards live as well and so replaces this setup rather than running beside it, or by any client of the API's
POST /api/import.
Running Telegraf instead?
Telegraf writes to the same endpoint with its stock outputs.influxdb_v2. That is a separate page, mostly because Telegraf's default inputs will eat your tag quota in a way Home Assistant's will not.
Endpoint for both: https://api.taghistorian.com
Common questions
- How do I keep Home Assistant history for longer than 10 days?
- Home Assistant's recorder purges after 10 days by default, but its long-term statistics table keeps hourly min, max and mean forever for any entity that has a state_class — locally, for free. You only need external storage if you want full resolution beyond 10 days, if the entity has no state_class, or if you want the history open to query somewhere other than the machine that records it. Surviving the machine alone is covered by Home Assistant's own automatic backups, if you store them off the box. The Tag Historian integration, installed through HACS, sends the entities you pick; without HACS, Home Assistant's built-in influxdb integration can write to any InfluxDB v2 endpoint, including Tag Historian.
- Do I need to install anything in Home Assistant?
- We recommend the Tag Historian integration, installed through HACS: a picker with your tag quota in view, the unit sent with every reading, an import of the history the recorder already holds, renamed entities followed, and a Repairs card when something goes wrong — see taghistorian.com/docs/home-assistant-hacs. It is also the way to send to Tag Historian while keeping a local InfluxDB, because the built-in integration holds only one connection. Without HACS, nothing has to be installed: the influxdb integration ships with Home Assistant, you add it under Settings → Devices & services, and its entity filter is a short block in configuration.yaml. That is this page, and it is supported too.
- Does the influxdb YAML configuration still work?
- Half of it. The connection — host, token, organization, bucket — is set up in the UI now. Home Assistant 2026.10 still imports those keys from configuration.yaml into a UI entry, but raises a Repairs card saying they are being removed, and that removal can land in any release. The entity filter (include and exclude), max_retries, precision and tags have no screen yet, so they stay in configuration.yaml and are read from there without any warning.
- Does one Home Assistant entity count as one tag?
- When its state is a number, yes: the entity becomes one tag named {domain}.{entity_id} — for example sensor.outdoor_temperature. An entity whose state is not a number, like a climate entity sitting at "heat", has no numeric state to store, so each of its numeric attributes becomes a tag of its own instead — several tags from one entity. The free plan includes 5 tags, so the include.entities filter is required reading, and it should name entities whose state is numeric.
- Are entity attributes stored?
- Not as history when the state itself is a number — then only the state is stored, and of the attributes only the friendly name is kept, as the tag’s description, so charts are labelled with the name Home Assistant shows. When the state is not a number there is nothing else to store, so every numeric attribute becomes its own tag. To keep one specific attribute as history, expose it as its own template sensor in Home Assistant, which costs one tag with a name you chose.