AirTag "integration" (user friendly + device tracker)

with this integration and apple airtag i can track when i left and came home ? if i can explain how if the phone and this tag will always be with me ?

Yes, you can.

However, i think there are better ways to do It in Home Assistant :sweat_smile:

How? please explain

There are multiple ways, based on GPS using device trackers, WiFi (i.e. NMAP) , Bluetooth (i.e. Bermuda) …

Hi,
do you resolve this problem?
I tried sensors.yaml, configuration.yaml but stil can’t see sensor.
Restarted HA and host.
In “check configuration”:
Configuration warnings

Platform error ‘device_tracker’ from integration ‘rest’ - No module named ‘homeassistant.components.rest.device_tracker’ Platform error ‘device_tracker’ from integration ‘template’ - No module named ‘homeassistant.components.template.device_tracker’

I use this guide

Thank you!

My code:



  - platform: rest
    name: airtag_karta_aiyato_geo
    value_template: "{{ value_json.results[0].formatted }}"
    json_attributes_path: "$.results[0]"
    json_attributes:
    - lon
    - lat
    verify_ssl: true
    scan_interval: 900 # every 15 min
    force_update: true
    resource_template: >
     {% set address = states('input_text.airtag').split('karta_aiyato')[1].split('•')[0] %}
     {% if address == "HOME" %}
      {% set home = "FULLADRESS" %}
      {{
        "https://api.geoapify.com/v1/geocode/search?text="
        + home | urlencode
        + "&apiKey=YOURAPYKEY&format=json"
      }}
     {% else %}
      {% set fix = address + "FIXADDRESS" %}
      {{
        "https://api.geoapify.com/v1/geocode/search?text="
        + fix | urlencode
        + "&apiKey=YOURAPYKEY&format=json"
      }}
     {% endif %}

  - platform: template
    sensors:
    airtag_karta_aiyato:
      friendly_name: "karta_aiyato"
      value_template: >
        {% set home = "STREETNAME" %} 
        {% if ":" in states('input_text.airtag').split('karta_aiyato')[1].split('•')[0] %} 
        {{ states('input_text.airtag').split('karta_aiyato')[1].split('•')[0].split(',')[0] }}
        {% elif home in states('input_text.airtag').split('karta_aiyato')[1].split('•')[0] %}Home
        {% else %}
        {{ states('sensor.airtag_karta_aiyato_geo') }}
        {% endif %}
      attribute_templates:
        latitude: >
          {% if ":" in states('input_text.airtag').split('karta_aiyato')[1].split('•')[0] %}null
          {% else %}{{ state_attr('sensor.airtag_karta_aiyato_geo','lat') }}
          {% endif %}
        longitude: >
          {% if ":" in states('input_text.airtag').split('karta_aiyato')[1].split('•')[0] %}null
          {% else %}{{ state_attr('sensor.airtag_karta_aiyato_geo','lon') }}
          {% endif %}
        status: >
          {% if ":" in states('input_text.airtag').split('karta_aiyato')[1].split('•')[0] %}unavailable
          {% else %}available
          {% endif %}
        last_update: "{{ as_timestamp(states.input_text.airtag.last_updated)|timestamp_custom ('%d/%m/%Y %H:%Mh') }}"
      icon_template: mdi:bag-personal

Sorry, but what does this integration do that the official iCloud one doesn’t?

The official just needs the tracker linked to the account, and you don’t need a “server” device sending the data manually. And I think you should still be able to use any cheap compatible tracker, right?

The iCloud would track phones and tablets, but not AirTags.

That said, the above was my understanding over last 2-3 years. can someone confirm this? Is it still the case as of September 2025, that for AirTags one would have to jump through the hoops…?

The only issue left is with the rest sensor, i get an undefined error for value_json … so its not parsing the “input_text.airtag” i assume leaving GPS coordinated empty in the sensor. Any ideas?

edit: after a long day the following addition to the code fixed the issue i had. this is especially for german user, when the location is shown as “Privat”

  resource_template: >
    {% set address = states('input_text.airtag').split('Airtag')[1].split('•')[0].strip() %}
    {% if address == "Privat" %}

And for the device tracker part you will need to change the following section to correctly show the device tracker “Home” when Location on Iphone is “Privat”


- platform: template
  sensors:
    airtag_airtag:
      friendly_name: "Airtag"
      value_template: >
        {% set home = "Privat" %} 
        {% if ":" in states('input_text.airtag').split('Airtag')[1].split('•')[0] %} 
        {{ states('input_text.airtag').split('Airtag')[1].split('•')[0].split(',')[0] }}
        {% elif home in states('input_text.airtag').split('Airtag')[1].split('•')[0] %}Home
        {% else %}
        {{ states('sensor.airtag_airtag_geo') }}
        {% endif %}
1 Like

I tried it but still I got the same log error… Antyhing else you changed? I have two Airtags, is it an issue? The input_text is all good ut it never sends anything to Geoapify…

And what is weird is that I can’t see the REST sensor in the entity list or using the Developer tool. So I can’t check whether it’s state is correct. Basically, it’s like the sensor.airtag_ITEM_geo has not been created. However, I have no error log apart from:

Logger: homeassistant.helpers.template
Source: helpers/template.py:2990
First occurred: 12:06:40 AM (5 occurrences)
Last logged: 12:08:46 AM

Template variable error: list object has no element 1 when rendering '{% set address = states('input_text.airtag').split('Cles')[1].split('•')[0].strip() %} {% if address == "Domicile" %} {% set home = "blablabla" %} {{ "https://api.geoapify.com/v1/geocode/search?text=" + home | urlencode + "&apiKey=blablabla&format=json" }} {% else %} {% set fix = address + "France" %} {{ "https://api.geoapify.com/v1/geocode/search?text=" + fix | urlencode + "&apiKey=blablabla&format=json" }} {% endif %}'
Template variable error: list object has no element 1 when rendering '{% set home = "blablabla" %} {% if ":" in states('input_text.airtag').split('Cles')[1].split('•')[0].strip() %} {{ states('input_text.airtag').split('Cles')[1].split('•')[0].split(',')[0].strip() }} {% elif home in states('input_text.airtag').split('Cles')[1].split('•')[0].strip() %}Home {% else %} {{ states('sensor.airtag_cles_geo') }} {% endif %}'
Template variable error: list object has no element 1 when rendering '{% if ":" in states('input_text.airtag').split('Cles')[1].split('•')[0].strip() %}null {% else %}{{ state_attr('sensor.airtag_cles_geo','lat') }} {% endif %}'
Template variable error: list object has no element 1 when rendering '{% if ":" in states('input_text.airtag').split('Cles')[1].split('•')[0].strip() %}null {% else %}{{ state_attr('sensor.airtag_cles_geo','lon') }} {% endif %}'
Template variable error: list object has no element 1 when rendering '{% if ":" in states('input_text.airtag').split('Cles')[1].split('•')[0].strip() %}unavailable {% else %}available {% endif %}'

And

Logger: homeassistant.components.template.template_entity
Source: components/template/template_entity.py:101
integration: Template (documentation, issues)
First occurred: 12:08:46 AM (4 occurrences)
Last logged: 12:08:46 AM

TemplateError('UndefinedError: list object has no element 1') while processing template 'Template<template=({% set home = "blablabla" %} {% if ":" in states('input_text.airtag').split('Cles')[1].split('•')[0].strip() %} {{ states('input_text.airtag').split('Cles')[1].split('•')[0].split(',')[0].strip() }} {% elif home in states('input_text.airtag').split('Cles')[1].split('•')[0].strip() %}Home {% else %} {{ states('sensor.airtag_cles_geo') }} {% endif %}) renders=6>' for attribute '_attr_native_value' in entity 'sensor.airtag_cles'
TemplateError('UndefinedError: list object has no element 1') while processing template 'Template<template=({% if ":" in states('input_text.airtag').split('Cles')[1].split('•')[0].strip() %}null {% else %}{{ state_attr('sensor.airtag_cles_geo','lat') }} {% endif %}) renders=6>' for attribute 'latitude' in entity 'sensor.airtag_cles'
TemplateError('UndefinedError: list object has no element 1') while processing template 'Template<template=({% if ":" in states('input_text.airtag').split('Cles')[1].split('•')[0].strip() %}null {% else %}{{ state_attr('sensor.airtag_cles_geo','lon') }} {% endif %}) renders=6>' for attribute 'longitude' in entity 'sensor.airtag_cles'
TemplateError('UndefinedError: list object has no element 1') while processing template 'Template<template=({% if ":" in states('input_text.airtag').split('Cles')[1].split('•')[0].strip() %}unavailable {% else %}available {% endif %}) renders=6>' for attribute 'status' in entity 'sensor.airtag_cles'

I tried with and without the strip() from @PX80 but still can’t find why it doesn’t work.

you will have to restart the REST Service in the Developer Menu … took me a day to figure out -.- … so once the REST Service was restarted you will see the geo sensor

2 Likes

Oh waaah! Magical! Thanks @PX80, I never had guessed that by myself. Maybe a good thing to add it to the Aguacatec tutorial @TiToTB ?

And it seems not to work properly when I add the multiple sensors in the sensor.yaml file.

Anyway, thanks so much for this project, the approach is quite an interesting! I wonder whether it is possible for an iPad to force the screenshot to be taken in portrait mode. As I crop the screenshot, it changes a lot if the person holds the iPad in portrait or landscape mode

It would also be interesting that if the screenshot or its interpretation fails, it doesn’t override the airtag address but keeps the last known one. Or at least this logic would apply for coordinates. What do you think?

yeah, would be great. i thin in this thread are some suggestions.

@TiToTB great project. loving it so far but run into issue with multiple tracker and think the main issue is with the shortcut but my understanding of shortcuts is very limited as well my fingers are to big to properly change things without messing it up.

1.) it seems the maps need to be present for the shortcut to work, correct?

edit: very weird, the update of the text sensor only works when the map is partially visible !?

edit2: so while the Num Object doesnt seem to work for me i render hard ranges.

However it seems that it can only store 5 objects in the airtag_text helper

Range Object 2-7

BlauPrivat • JetztBei dir
CardPrivat • Zuletzt gesehen: vor 1 Std.0 km
GreenPrivat • JetztBei dir
AirtagPrivat • Vor 11 Min.0 km
LilaZuletzt gesehen: vor 2 Sta.7 km


Range Object 3-7

Card0 kmPrivat • Vor 1 Min.
GreenBei dirPrivat • Jetzt
Airtag0 km
Privat • Vor 17 Min.Lila7 kmZuletzt gesehen: vor 2 Std.
Rosa7 kmZuletzt gesehen: vor 2 Std.Gefundenes Objekt identifizieren苁PersonenGeräteObjekteIch

So shifting the starting Range, we can see first Tracker “Blau” is being discarded and last Tracker “Rosa” is being added.

So where is the limitation as the max. Char Count hasnt been reached?

it seems with more than 4 we overload the helper and its not displaying anything. so yes the shotcut collect all the correct infirmation but when seind to HA it gets dropped. Did you figure out a suitable solution?

Also anyone got a solution to not overwrite the last known adress with “last seen XX ago not haivng an adress” ?

edit: create a new apple shortcut as per AirTag “integration” (user friendly + device tracker) - Share your Projects! - Home Assistant Community and got it working with multiple tracker

I did not try it anymore (lack of time), but I will try soon.
Thanks for sharing

The biggest challenge for me with multiple tracker is, that the IOS Gui Randomly Swap the TrackerDevice List.

So when i tell the shortcut to use the first 3 items and then the last3 items and send them to input_text.airtag1 and the other to input_text.airtag2 helper … i have a problem with the template, since the template expect Tracker1 to be in input_text.airtag1

If anyone has already worked around this,please share

tkanks @manuelm23. any solution to force the ipad to be in portrait mode when doing the screenshot?

Thanks for your Guide @TiToTB

Helper already get information from airtag, but I still cant find sensor.airtag

Here my sensors.yaml config


And I already call sensors.yaml in configuration