{"id":13479013,"url":"https://github.com/evanjd/python-logi-circle","last_synced_at":"2026-03-16T16:39:45.008Z","repository":{"id":32901500,"uuid":"144780990","full_name":"evanjd/python-logi-circle","owner":"evanjd","description":"Python 3.7+ API for Logi Circle cameras","archived":false,"fork":false,"pushed_at":"2024-01-30T00:03:58.000Z","size":179,"stargazers_count":24,"open_issues_count":2,"forks_count":6,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-03-06T07:19:47.746Z","etag":null,"topics":["aiohttp","asyncio","home-automation","logi-circle","python","python3","surveillance"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/evanjd.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-08-14T23:09:38.000Z","updated_at":"2025-02-02T18:05:38.000Z","dependencies_parsed_at":"2024-06-19T11:16:23.051Z","dependency_job_id":"10331a25-1891-4866-a2d8-caa7adb4a3b1","html_url":"https://github.com/evanjd/python-logi-circle","commit_stats":{"total_commits":103,"total_committers":3,"mean_commits":"34.333333333333336","dds":"0.058252427184465994","last_synced_commit":"804d3f4b5a69ae96186b7c7b6c291856099f0b52"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evanjd%2Fpython-logi-circle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evanjd%2Fpython-logi-circle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evanjd%2Fpython-logi-circle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evanjd%2Fpython-logi-circle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/evanjd","download_url":"https://codeload.github.com/evanjd/python-logi-circle/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245809837,"owners_count":20676068,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aiohttp","asyncio","home-automation","logi-circle","python","python3","surveillance"],"created_at":"2024-07-31T16:02:07.681Z","updated_at":"2025-12-13T16:38:47.440Z","avatar_url":"https://github.com/evanjd.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"# Python Logi Circle API\n\n\u003e Python 3.7+ API for interacting with Logi Circle cameras, written with asyncio and aiohttp.\n\n[![PyPI version](https://badge.fury.io/py/logi-circle.svg)](https://badge.fury.io/py/logi-circle)\n![License](https://img.shields.io/packagist/l/doctrine/orm.svg)\n[![Build Status][github-actions-badge]][github-actions-url]\n[![Coverage Status][coverage-badge]][coverage-url]\n[![Open Issues][open-issues-badge]][open-issues-url]\n\n:warning: **This library is in maintenance mode. Logitech has ceased all support for individual users of the API and no longer issues API keys.** :warning:\n\nThis library exposes the [Logi Circle](https://www.logitech.com/en-us/product/circle-2-home-security-camera) family of cameras as Python objects, wrapping Logi Circle's official API.\n\n[Now available as a Home Assistant integration!](https://www.home-assistant.io/components/logi_circle/) :tada:\n\nThere are two versions of this API:\n\n- `2.x` - which targets the public API **(you are here)**\n- [`1.x`](https://github.com/evanjd/python-logi-circle/tree/private-api) - which targets the private API ([`private-api` branch](https://github.com/evanjd/python-logi-circle/tree/private-api))\n\n## Features implemented\n\n- Download real-time live stream data to disk or serve to your application as a raw bytes object\n- Download any activity video to disk or serve to your application as a raw bytes object\n- Download still images from camera to disk or serve to your application as a raw bytes object\n- Query/filter the activity history by start time and/or activity properties (duration, relevance)\n- Set name, timezone, streaming mode and privacy mode of a given camera\n- On-demand polling from server to update camera properties\n- Subscribe to WebSocket API to handle camera property updates and activities pushed from API\n- Read camera properties (see \"play with props\" example)\n\n## Usage example\n\n#### Setup and authenticate:\n\n```python\nimport asyncio\nfrom logi_circle import LogiCircle\n\nlogi = LogiCircle(client_id='your-client-id',\n                  client_secret='your-client-secret',\n                  redirect_uri='https://your-redirect-uri',\n                  api_key='your-api-key')\n\nif not logi.authorized:\n    print('Navigate to %s and enter the authorization code passed back to your redirect URI' % (logi.authorize_url))\n    code = input('Code: ')\n\n    async def authorize():\n        await logi.authorize(code)\n        await logi.close()\n\n    asyncio.get_event_loop().run_until_complete(authorize())\n```\n\n#### Grab latest still image:\n\n```python\nasync def get_snapshot_images():\n    for camera in await logi.cameras:\n        if camera.streaming:\n            await camera.live_stream.download_jpeg(filename='%s.jpg' % (camera.name),\n                                                   quality=75,  # JPEG compression %\n                                                   refresh=False)  # Don't force cameras to wake\n    await logi.close()\n\nasyncio.get_event_loop().run_until_complete(get_snapshot_images())\n```\n\n#### Download 30s of live stream video from 1st camera (requires ffmpeg):\n\n```python\nasync def get_livestream():\n    camera = (await logi.cameras)[0]\n    filename = '%s-livestream.mp4' % (camera.name)\n\n    await camera.live_stream.download_rtsp(filename=filename,\n                                           duration=30)\n\n    await logi.close()\n\nasyncio.get_event_loop().run_until_complete(get_livestream())\n```\n\n#### Download latest activity for all cameras:\n\n```python\nasync def get_latest_activity():\n    for camera in await logi.cameras:\n            last_activity = await camera.last_activity\n            if last_activity:\n                # Get activity as image\n                await last_activity.download_jpeg(filename='%s-last-activity.jpg' % (camera.name))\n                # Get activity as video\n                await last_activity.download_mp4(filename='%s-last-activity.mp4' % (camera.name))\n\n    await logi.close()\n\nasyncio.get_event_loop().run_until_complete(get_latest_activity())\n```\n\n#### Turn off streaming for all cameras:\n\n```python\nasync def disable_streaming_all():\n    for camera in await logi.cameras:\n        if camera.streaming:\n            await camera.set_config(prop='streaming',\n                                    value=False)\n            print('%s is now off.' % (camera.name))\n        else:\n            print('%s is already off.' % (camera.name))\n    await logi.close()\n\nasyncio.get_event_loop().run_until_complete(disable_streaming_all())\n```\n\n#### Subscribe to camera events with WS API:\n\n```python\nasync def subscribe_to_events():\n    subscription = await logi.subscribe(['accessory_settings_changed',\n                                         \"activity_created\",\n                                         \"activity_updated\",\n                                         \"activity_finished\"])\n    while True:\n        await subscription.get_next_event()\n\nasyncio.get_event_loop().run_until_complete(subscribe_to_events())\n```\n\n#### Play with props:\n\n```python\nasync def play_with_props():\n    for camera in await logi.cameras:\n        last_activity = await camera.get_last_activity()\n        print('%s: %s' % (camera.name,\n                          ('is charging' if camera.charging else 'is not charging')))\n        if camera.battery_level \u003e= 0:\n            print('%s: %s%% battery remaining' %\n                  (camera.name, camera.battery_level))\n            print('%s: Battery saving mode is %s' %\n                  (camera.name, 'on' if camera.battery_saving else 'off'))\n        print('%s: Model number is %s' % (camera.name, camera.model))\n        print('%s: Mount is %s' % (camera.name, camera.mount))\n        print('%s: Signal strength is %s%% (%s)' % (\n            camera.name, camera.signal_strength_percentage, camera.signal_strength_category))\n        if last_activity:\n            print('%s: last activity was at %s and lasted for %s seconds.' % (\n                camera.name, last_activity.start_time.isoformat(), last_activity.duration.total_seconds()))\n        print('%s: Firmware version %s' % (camera.name, camera.firmware))\n        print('%s: MAC address is %s' % (camera.name, camera.mac_address))\n        print('%s: Microphone is %s and gain is set to %s (out of 100)' % (\n            camera.name, 'on' if camera.microphone else 'off', camera.microphone_gain))\n        print('%s: Speaker is %s and volume is set to %s (out of 100)' % (\n            camera.name, 'on' if camera.speaker else 'off', camera.speaker_volume))\n        print('%s: LED is %s' % (\n            camera.name, 'on' if camera.led else 'off'))\n        print('%s: Recording mode is %s' % (\n            camera.name, 'on' if camera.recording else 'off'))\n    await logi.close()\n\nasyncio.get_event_loop().run_until_complete(play_with_props())\n```\n\n## Thanks\n\n- This first version of API borrowed a lot of the design and some utility functions from [tchellomello's](https://github.com/tchellomello) [Python Ring Doorbell](https://github.com/tchellomello/python-ring-doorbell) project. It made a great template for how to implement a project like this, so thanks!\n- Thanks [sergeymaysak](https://github.com/sergeymaysak) for suggesting a switch to aiohttp, it made integrating with Home Assistant much easier.\n- Logitech for reaching out and providing support to reimplement this library using their official API.\n\n## Contributing\n\nPull requests are very welcome, every little bit helps!\n\n1. Raise an issue with your feature request or bug before starting work.\n2. Fork it (\u003chttps://github.com/evanjd/python-logi-circle/fork\u003e).\n3. Create your feature branch (`git checkout -b feature/fooBar`).\n4. Commit your changes (`git commit -am 'Add some fooBar'`).\n5. Add/update tests if needed, then run `tox` to confirm no test failures.\n6. Push to the branch (`git push origin feature/fooBar`).\n7. Create a new pull request!\n\n## Meta\n\nEvan Bruhn – [@evanjd](https://github.com/evanjd) – evan.bruhn@gmail.com\n\nDistributed under the MIT license. See `LICENSE` for more information.\n\n\u003c!-- Markdown link \u0026 img dfn's --\u003e\n\n[open-issues-badge]: https://img.shields.io/github/issues/evanjd/python-logi-circle.svg\n[open-issues-url]: https://github.com/evanjd/python-logi-circle/issues\n[github-actions-badge]: https://github.com/evanjd/python-logi-circle/actions/workflows/python-package.yml/badge.svg\n[github-actions-url]: https://github.com/evanjd/python-logi-circle/actions/workflows/python-package.yml\n[coverage-badge]: https://img.shields.io/coveralls/github/evanjd/python-logi-circle/master.svg\n[coverage-url]: https://coveralls.io/github/evanjd/python-logi-circle?branch=master\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fevanjd%2Fpython-logi-circle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fevanjd%2Fpython-logi-circle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fevanjd%2Fpython-logi-circle/lists"}