base on ๐Ÿ + ๐ŸŽฏ + ๐Ÿ = Query Apple's FindMy Network with Python! <div align="center"> <img alt="FindMy.py Logo" src="https://raw.githubusercontent.com/malmeloo/FindMy.py/refs/heads/main/assets/icon.png" width="500"> <h1>FindMy.py</h1> </div> <div align="center"> _Query Apple's FindMy network with Python!_ <h5> <a href="https://docs.mikealmel.ooo/FindMy.py"> Docs </a> <span> | </span> <a href="examples/"> Examples </a> <span> | </span> <a href="https://pypi.org/project/FindMy/"> PyPI </a> <span> | </span> <a href="https://discord.gg/EF6UCG2TF6"> Discord </a> </div> ## ๐Ÿš€ Overview The current "Find My-scene" is quite fragmented, with code being all over the place across multiple repositories, written by [several authors](#-credits). This makes it hard to integrate FindMy functionality with your project. FindMy.py aims to make it easy for you to query the location of your AirTags, iDevices and DIY tags with an easy to use Python library. ## ๐Ÿงช Features - [x] Cross-platform: no Mac needed - [x] Fetch and decrypt location reports - [x] Official accessories (AirTags, iDevices, etc.) - [x] Custom AirTags (OpenHaystack) - [x] Apple account sign-in - [x] SMS 2FA support - [x] Trusted Device 2FA support - [x] Scan for nearby FindMy-devices - [x] Decode their info, such as public keys and status bytes - [x] Import or create your own accessory keys - [x] Both async and sync APIs ## ๐Ÿ“ฅ Installation The package can be installed from [PyPi](https://pypi.org/project/findmy/): ```shell pip install findmy ``` For usage examples, see the [examples](examples) directory. We are also building out a CLI. Try `python -m findmy` to see the current state of it. Documentation can be found [here](http://docs.mikealmel.ooo/FindMy.py/). ## ๐Ÿค Contributing Want to contribute code? That's great! For new features, please open an [issue](https://github.com/malmeloo/FindMy.py/issues) first so we can discuss. This project uses [Ruff](https://docs.astral.sh/ruff/) for linting and formatting. Before opening a pull request, please ensure that your code adheres to these rules. There are pre-commit hooks included to help you with this, which you can set up as follows: ```shell pip install uv uv sync # this installs ruff & pre-commit into your environment pre-commit install ``` After following the above steps, your code will be linted and formatted automatically before committing it. ## ๐Ÿง  Derivative projects There are several other cool projects in the FindMy space! You can check them out [here](http://docs.mikealmel.ooo/FindMy.py/related/index.html). ## ๐Ÿ… Credits While I designed the library, the vast majority of actual functionality is made possible by the following wonderful people and organizations: - @seemo-lab for [OpenHaystack](https://github.com/seemoo-lab/openhaystack/) and their [research](https://doi.org/10.2478/popets-2021-0045); - @JJTech0130 for [Pypush](https://github.com/JJTech0130/pypush), providing the breakthrough necessary for getting this to work without a Mac; - @biemster for [FindMy](https://github.com/biemster/FindMy), which is the main basis of this project; - @Dadoum for [pyprovision](https://github.com/Dadoum/pyprovision/) and [anisette-v3-server](https://github.com/Dadoum/anisette-v3-server); - @nythepegasus for [GrandSlam](https://github.com/nythepegasus/grandslam/) SMS 2FA; - And probably more, so let me know! :D ", Assign "at most 3 tags" to the expected json: {"id":"12537","tags":[]} "only from the tags list I provide: [{"id":77,"name":"3d"},{"id":89,"name":"agent"},{"id":17,"name":"ai"},{"id":54,"name":"algorithm"},{"id":24,"name":"api"},{"id":44,"name":"authentication"},{"id":3,"name":"aws"},{"id":27,"name":"backend"},{"id":60,"name":"benchmark"},{"id":72,"name":"best-practices"},{"id":39,"name":"bitcoin"},{"id":37,"name":"blockchain"},{"id":1,"name":"blog"},{"id":45,"name":"bundler"},{"id":58,"name":"cache"},{"id":21,"name":"chat"},{"id":49,"name":"cicd"},{"id":4,"name":"cli"},{"id":64,"name":"cloud-native"},{"id":48,"name":"cms"},{"id":61,"name":"compiler"},{"id":68,"name":"containerization"},{"id":92,"name":"crm"},{"id":34,"name":"data"},{"id":47,"name":"database"},{"id":8,"name":"declarative-gui "},{"id":9,"name":"deploy-tool"},{"id":53,"name":"desktop-app"},{"id":6,"name":"dev-exp-lib"},{"id":59,"name":"dev-tool"},{"id":13,"name":"ecommerce"},{"id":26,"name":"editor"},{"id":66,"name":"emulator"},{"id":62,"name":"filesystem"},{"id":80,"name":"finance"},{"id":15,"name":"firmware"},{"id":73,"name":"for-fun"},{"id":2,"name":"framework"},{"id":11,"name":"frontend"},{"id":22,"name":"game"},{"id":81,"name":"game-engine "},{"id":23,"name":"graphql"},{"id":84,"name":"gui"},{"id":91,"name":"http"},{"id":5,"name":"http-client"},{"id":51,"name":"iac"},{"id":30,"name":"ide"},{"id":78,"name":"iot"},{"id":40,"name":"json"},{"id":83,"name":"julian"},{"id":38,"name":"k8s"},{"id":31,"name":"language"},{"id":10,"name":"learning-resource"},{"id":33,"name":"lib"},{"id":41,"name":"linter"},{"id":28,"name":"lms"},{"id":16,"name":"logging"},{"id":76,"name":"low-code"},{"id":90,"name":"message-queue"},{"id":42,"name":"mobile-app"},{"id":18,"name":"monitoring"},{"id":36,"name":"networking"},{"id":7,"name":"node-version"},{"id":55,"name":"nosql"},{"id":57,"name":"observability"},{"id":46,"name":"orm"},{"id":52,"name":"os"},{"id":14,"name":"parser"},{"id":74,"name":"react"},{"id":82,"name":"real-time"},{"id":56,"name":"robot"},{"id":65,"name":"runtime"},{"id":32,"name":"sdk"},{"id":71,"name":"search"},{"id":63,"name":"secrets"},{"id":25,"name":"security"},{"id":85,"name":"server"},{"id":86,"name":"serverless"},{"id":70,"name":"storage"},{"id":75,"name":"system-design"},{"id":79,"name":"terminal"},{"id":29,"name":"testing"},{"id":12,"name":"ui"},{"id":50,"name":"ux"},{"id":88,"name":"video"},{"id":20,"name":"web-app"},{"id":35,"name":"web-server"},{"id":43,"name":"webassembly"},{"id":69,"name":"workflow"},{"id":87,"name":"yaml"}]" returns me the "expected json"