Python implementation of Growatt public REST API
Project description
GrowattApi
A python implementation of Growatt's public API.
Motivation
There are already other libraries accessing Growatt's APIs, they all use reverse-engineered calls to internal, undocumented APIs.
- for example, see the faboulous work of indykoning at PyPi_GrowattServer used e.g. in HomeAssistant
This package aims to
- use type-aware pydantic objects as return values
- use Growatt's public API documented
- here (v1)
- /v1/ endpoints
- user/plant management
- metrics
- settings read/write
- inv/storage/max/sph/spa/min/pcs/hps/pbd/smart_meter/env_sensor/vpp/groboost (no wit/sph-s/noah)
- here (v4)
- /v4/new-api endpoints
- no user/plant management
- new endpoints for metrics
- settings write only on/off and NOAH time periods
- inv/storage/sph/max/spa/min/wit/sph-s/noah (no pcs/hps/pbd/smart_meter/env_sensor/vpp/groboost)
- here (v1/v4 mixed)
- mixed documentation - different sorting
- vpp settings (in addition to other /v4/ docs)
- here (/v1/v4 postman)
- postman collection implementing some (known) endpoints
- here (v1)
Implementation status
Alpha: The library is roughly feature-complete, but not yet proven to be working for users other than me.
Note:
Reading/writing settings seems not to work. All tries I did returned "error code 1: SYSTEM_ERROR" :( (But still I was able to set my inverter to standby mode, so it seems to work despite the error message)
Usage
Installation
This package is available at PiPy and can be installed using pip:
pip install growatt-public-api
Login
The API requires token authentication. The token can be retrieved via
- Growatt Android/iOS app "ShinePhone"
- go to "Me" -> your username -> "API Token"
- copy your token or request an new one
- Growatt web frontend at openapi.growatt.com
- login
- click your username in the upper right corner
- go to "Account Management" -> "API Token"
- copy your token or request a new one
Pass the token when creating the API object
from growatt_api import GrowattApi
api = GrowattApi(
token="your_token",
# for using a server other than "https://openapi.growatt.com", set the optional "server_url" parameter
# server_url="https://openapi-cn.growatt.com", # China
# server_url="https://openapi-us.growatt.com", # North America
# server_url="http://openapi-au.growatt.com", # Australia and New Zealand
# server_url="https://openapi.growatt.com", # Europe and rest of world
# server_url="http://ess-server.atesspower.com", # for ATESS users
)
Examples
get your plant ID
plant_list = api.plant.list()
plant_id = plant_list.data.plants[0].plant_id
print(f"{plant_id=}")
# => plant_id=1234567
get your devices
device_list = api.plant.list_devices(plant_id=plant_id)
device_sn = device_list.data.devices[0].device_sn
device_type = api.device.get_device_type(device_sn=device_sn)
print(f"{device_type=}, {device_sn=}")
# => device_type=DeviceType.MIN, device_sn='BZP0000000'
query device metrics
Option 1: use device-specifc API explicitly
Use the submodule matching your device type to retrieve its metrics or settings
Note: Make sure to use device.get_device_type() for retrieving your device type - the internal type may differ form the marketing name.
min_details = api.min.details(device_sn=device_sn)
print(min_details.data.model_dump_json())
# => {"alias":"BZP0000000","datalogger_sn":"QMN0000000000000","e_today":0.0,...}
Option 2: use the convenience API to automatically detect and use the correct device type
Here, retrieve the correct decive API's instance by using api.api_for_device(device_sn=device_sn).
In following calls, the device_sn does not need to be supplied anymore.
my_device = api.api_for_device(device_sn=device_sn)
# my_device will be of type `Min` for MIN devices with device_sn pre-set
min_details = my_device.details()
print(min_details.data.model_dump_json())
# => {"alias":"BZP0000000","datalogger_sn":"QMN0000000000000","e_today":0.0,...}
Submodules and methods
User
- list users
user.list()
- check username available
user.check_username()
- add user
user.register()
- modify user information
user.modify()
Plant
- plant management
- add new plant
plant.add() - modify plant
plant.modify() - delete plant
plant.delete() - add inverter to plant
plant.add_device() - add datalogger to plant
plant.add_datalogger() - remove datalogger from plant
plant.remove_datalogger()
- add new plant
- list plants
plant.list()plant.list_by_user()
- plant details
plant.details()
- power/energy overview
plant.energy_overview()
- energy history
plant.energy_history()
- power metrics by day
plant.power()
- list devices assigned to plant
- list dataloggers
plant.list_dataloggers() - list inverters/storage
plant.list_devices()
- list dataloggers
Datalogger
- verify datalogger's CC code
device.datalogger_validate()
- get sensors attached to datalogger
- get smart meters
datalogger.list_smart_meters() - get environmental sensors
datalogger.list_env_sensors()
- get smart meters
Device (ALL inverter types)
- get devices (inverters) assigned to current user
device.list()- see also
plant.list_devices()plant.list_dataloggers()datalogger.list_smart_meters()datalogger.list_env_sensors()
- query device type
device.get_device_type()*** use this method to query your inverter's type ***
- get device creation date
device.create_date()
- device power/energy metrics
- get energy (sum) for specific day
device.energy_day()
- get energy (sum) for specific day
- get device tree
- get plant by device_sn
device.get_plant() - get datalogger by device_sn
device.get_datalogger()
- get plant by device_sn
Inverter (DeviceType.INVERTER)
- general device data
- read device data
inverter.details()inverter.details_v4()(using new API)
- read alarms/notification
inverter.alarms()
- read device data
- device power/energy metrics
- current
inverter.energy()inverter.energy_v4()(using new API)inverter.energy_multiple()
- historical data
inverter.energy_history()inverter.energy_history_v4()(using new API)inverter.energy_history_multiple_v4()(using new API)- Note: historical data seems to be restricted to 95 days - for earlier dates, API does not return anything
- current
- device settings
- read settings value
inverter.setting_read() - write settings value
inverter.setting_write()(use with caution)inverter.setting_write_on_off()(using new API)inverter.setting_write_active_power()(using new API)
- read settings value
Storage (DeviceType.STORAGE)
- general device data
- read device data
storage.details()storage.details_v4()(using new API)
- read alarms/notification
storage.alarms()
- read device data
- device power/energy metrics
- current
storage.energy()storage.energy_v4()(using new API)
- historical data
storage.energy_history()storage.energy_history_v4()(using new API)storage.energy_history_multiple_v4()(using new API)- Note: historical data seems to be restricted to 95 days - for earlier dates, API does not return anything
- current
- device settings
- read settings value
storage.setting_read() - write settings value
storage.setting_write()(use with caution)storage.setting_write_on_off()(using new API)storage.setting_write_active_power()(using new API)
- read settings value
MAX (DeviceType.MAX)
- general device data
- read device data
max.details()max.details_v4()(using new API)
- read alarms/notification
max.alarms()
- read device data
- device power/energy metrics
- current
max.energy()max.energy_multiple()max.energy_v4()(using new API)
- historical data
max.energy_history()max.energy_history_v4()(using new API)max.energy_history_multiple_v4()(using new API)- Note: historical data seems to be restricted to 95 days - for earlier dates, API does not return anything
- current
- device settings
- read settings value
max.setting_read() - write settings value
max.setting_write()(use with caution)max.setting_write_on_off()(using new API)max.setting_write_active_power()(using new API)
- read settings value
SPH (DeviceType.SPH - (MIX))
- general device data
- read device data
sph.details()sph.details_v4()(using new API)
- read alarms/notification
sph.alarms()
- read device data
- device power/energy metrics
- current
sph.energy()sph.energy_multiple()sph.energy_v4()(using new API)
- historical data
sph.energy_history()sph.energy_history_v4()(using new API)sph.energy_history_multiple_v4()(using new API)- Note: historical data seems to be restricted to 95 days - for earlier dates, API does not return anything
- current
- device settings
- read settings value
sph.setting_read()sph.setting_read_vpp_param()(using new API)
- write settings value
sph.setting_write()(use with caution)sph.setting_write_on_off()(using new API)sph.setting_write_active_power()(using new API)sph.setting_write_vpp_param()(using new API)
- VPP (VirtualPowerPlant) settings
- get current State-of-Charge (SOC)
sph.soc() - read vpp schedules
sph.setting_read_vpp_param()(using new API)
- write vpp schedules
sph.setting_write_vpp_now()sph.setting_write_vpp_schedule()sph.setting_write_vpp_param()(using new API)
- get current State-of-Charge (SOC)
- read settings value
SPA (DeviceType.SPA)
- general device data
- read device data
spa.details()spa.details_v4()(using new API)
- read alarms/notification
spa.alarms()
- read device data
- device power/energy metrics
- current
spa.energy()spa.energy_multiple()spa.energy_v4()(using new API)
- historical data
spa.energy_history()spa.energy_history_v4()(using new API)spa.energy_history_multiple_v4()(using new API)- Note: historical data seems to be restricted to 95 days - for earlier dates, API does not return anything
- current
- device settings
- read settings value
spa.setting_read()
- write settings value
spa.setting_write()(use with caution)spa.setting_write_on_off()(using new API)spa.setting_write_active_power()(using new API)
- VPP (VirtualPowerPlant) settings
- get current State-of-Charge (SOC)
spa.soc() - read vpp schedules
spa.setting_read_vpp_param()(using new API)
- write vpp schedules
spa.setting_write_vpp_now()spa.setting_write_vpp_schedule()spa.setting_write_vpp_param()(using new API)
- get current State-of-Charge (SOC)
- read settings value
MIN (DeviceType.MIN - TLX/MIN/MAC/MOD-XH/MID-XH/NEO)
- general device data
- read device data
min.details()min.details_v4()(using new API)
- read alarms/notification
min.alarms()
- read device data
- device power/energy metrics
- current
min.energy()min.energy_v4()(using new API)min.energy_multiple()
- historical data
min.energy_history()min.energy_history_v4()(using new API)min.energy_history_multiple_v4()(using new API)- Note: historical data seems to be restricted to 95 days - for earlier dates, API does not return anything
- current
- device settings
- read settings overview
min.settings() - read settings value
min.setting_read()
- write settings value
min.setting_write()(use with caution)min.setting_write_on_off()(using new API)min.setting_write_active_power()(using new API)
- VPP (VirtualPowerPlant) settings
- get current State-of-Charge (SOC)
min.soc() - read vpp schedules
min.setting_read_vpp_param()(using new API)
- write vpp schedules
min.setting_write_vpp_now()min.setting_write_vpp_schedule()min.setting_write_vpp_param()(using new API)
- get current State-of-Charge (SOC)
- read settings overview
PCS (DeviceType.PCS)
- general device data
- read device data
pcs.details() - read alarms/notification
pcs.alarms()
- read device data
- device power/energy metrics
- current
pcs.energy() - historical data
pcs.energy_history()- Note: historical data seems to be restricted to 95 days - for earlier dates, API does not return anything
- current
HPS (DeviceType.HPS)
- general device data
- read device data
hps.details() - read alarms/notification
hps.alarms()
- read device data
- device power/energy metrics
- current
hps.energy() - historical data
hps.energy_history()- Note: historical data seems to be restricted to 95 days - for earlier dates, API does not return anything
- current
PBD (DeviceType.PBD)
- general device data
- read device data
pbd.details() - read alarms/notification
pbd.alarms()
- read device data
- device power/energy metrics
- current
pbd.energy() - historical data
pbd.energy_history()- Note: historical data seems to be restricted to 95 days - for earlier dates, API does not return anything
- current
WIT (DeviceType.WIT)
Note: WIT devices are not supported by APIv1 endpoints - only v4 endpoints available
- general device data
- read device data
wit.details_v4()(using new API)
- read device data
- device power/energy metrics
- current
wit.energy_v4()(using new API)
- historical data
wit.energy_history_v4()(using new API)wit.energy_history_multiple_v4()(using new API)- Note: historical data seems to be restricted to 95 days - for earlier dates, API does not return anything
- current
- device settings
- write settings value
wit.setting_write_on_off()(using new API)wit.setting_write_active_power()(using new API)
- VPP (VirtualPowerPlant) settings
- read vpp schedules
wit.setting_read_vpp_param()(using new API)
- write vpp schedules
wit.setting_write_vpp_param()(using new API)
- read vpp schedules
- write settings value
SPH-S (DeviceType.SPHS)
Note: SPH-S devices are not supported by APIv1 endpoints - only v4 endpoints available
- general device data
- read device data
sphs.details_v4()(using new API)
- read device data
- device power/energy metrics
- current
sphs.energy_v4()(using new API)
- historical data
sphs.energy_history_v4()(using new API)sphs.energy_history_multiple_v4()(using new API)- Note: historical data seems to be restricted to 95 days - for earlier dates, API does not return anything
- current
- device settings
- write settings value
sphs.setting_write_on_off()(using new API)sphs.setting_write_active_power()(using new API)
- VPP (VirtualPowerPlant) settings
- read vpp schedules
sphs.setting_read_vpp_param()(using new API)
- write vpp schedules
sphs.setting_write_vpp_param()(using new API)
- read vpp schedules
- write settings value
NOAH (DeviceType.NOAH - NOAH/NEXA)
Note: Noah devices are not supported by APIv1 endpoints - only v4 endpoints available
- general device data
- read device data
noah.details_v4()(using new API)
- read device data
- device power/energy metrics
- current
noah.energy_v4()(using new API)
- historical data
noah.energy_history_v4()(using new API)noah.energy_history_multiple_v4()(using new API)- Note: historical data seems to be restricted to 95 days - for earlier dates, API does not return anything
- current
- device settings
- read settings value
noah.setting_read_vpp_param()(using new API)
- write settings value
noah.setting_write_on_off()(using new API)noah.setting_write_active_power()(using new API)noah.setting_write_vpp_param()(using new API)
- VPP (VirtualPowerPlant) settings
- read vpp schedules
noah.setting_read_vpp_param()(using new API)
- write vpp schedules
noah.setting_write_vpp_param()(using new API)
- read vpp schedules
- read settings value
GroBoost (DeviceType.GROBOOST)
- general device data
- read device data
groboost.details()
- read device data
- device metrics
- current
groboost.metrics() - current for multiple devices
groboost.metrics_multiple() - historical data
groboost.metrics_history()- Note: historical data seems to be restricted to 95 days - for earlier dates, API does not return anything
- current
Smart meter (DeviceType.OTHER - SmartMeter/SDM/CHNT)
- get meters attached to datalogger
datalogger.list_smart_meters()
- device power/energy metrics
- current
smart_meter.energy() - historical data
smart_meter.energy_history()- Note: historical data seems to be restricted to 95 days - for earlier dates, API does not return anything
- current
Environmental sensor (DeviceType.OTHER - Temperature/Humidity/Wind/...)
- get sensors attached to datalogger
datalogger.list_env_sensors()
- device metrics
- current
env_sensor.metrics() - historical data
env_sensor.metrics_history()- Note: historical data seems to be restricted to 95 days - for earlier dates, API does not return anything
- current
Contribution guidelines
If you see any bugs or improvement ideas, I would love to see a contribution from you.
Your options include
- Open an issue describing the bug or improvement idea
- Implement your changes and open a PR
- run
flake8andblackon your code before committing - you can do this by using the pre-commit config of this rfepo
pip install pre-commit cd GrowattPublicApiPy pre-commit install # git commit ...
- run
Contribution ideas
- run code for different inverter types
- I have a NEO (=MIN) and NEXA (=NOAH) inverter for testing, and I found some devices on the test environments, but some device types remain untested.
- just try to run the code for your inverter model and check the pydantic models are valid
- anything else you can think of
Disclaimer
The developers & maintainers of this library accept no responsibility for any damage, problems or issues that arise with your Growatt systems as a result of its use.
The library contains functions that allow you to modify the configuration of your plant & inverter which carries the ability to set values outside of normal operating parameters, therefore, settings should only be modified if you understand the consequences.
To the best of our knowledge only the settings functions perform modifications to your system and all other operations are read only. Regardless of the operation:
The library is used entirely at your own risk.
TODOs
- TODO: generate & publish docs
Changelog
- 2025.08.17 (alpha)
- added NOAH/NEXA support (verified with real NEXA-2000 device)
- 2025.07.14 (alpha)
- packaging & deploy to PyPi
- removed truststore SSL certificate injection
- 2025.07.11 (pre-alpha)
- moved common pydantic models (e.g.
GrowattTimeCalendar) to common module - cache API requests (using TMP directory) to avoid 'API rate limit exceeded' errors
- moved common pydantic models (e.g.
- 2025.06.03 (pre-alpha)
- new example for MIN devices (e.g. NEO)
- convenience method
api_for_device()for retrieving device-specific APIfrom growatt_api import GrowattApi api = GrowattApi(token="your_token") # now you can get your device-specifc api by my_device = api.api_for_device(device_sn="your_device_sn") # this returns e.g. `api.min` for MIN devices # arguments "device_sn" does not need to be supplied anymore, so you can do e.g. min_details = my_device.details() # instead of min_details = api.min.details(device_sn="your_device_sn") print(min_details.data.model_dump_json())
- 2025.05.22 (pre-alpha)
- refactoring: moved some endpoints from/to plant/device/datalogger
- refactoring: moved some endpoints from/to smart_meter/env_sensor/datalogger
- common device type
growatt_public_api.DeviceType- retrieve device type by
api.device.get_device_type()
- retrieve device type by
- refactoring: integrate v4 endpoints in "normal" code (use submodule instead of device_type parameter)
- refactoring: integrate VPP into MIN,SPA,SPH
- 2025.05.12 (pre-alpha)
- add tests to verify returned parameters are same as expected parameters
- 2025.03.28 (pre-alpha)
- v4/new-api endpoints implemented
- 2025.03.11 (pre-alpha)
- all API v1 endpoints implemented
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file growatt_public_api-2025.8.17.tar.gz.
File metadata
- Download URL: growatt_public_api-2025.8.17.tar.gz
- Upload date:
- Size: 244.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
641fcb350b279b73f31149ae2a591bbdbe366ba2051acb19031803b2605d5452
|
|
| MD5 |
0d80baf7eaf13f0f3f76fc47f5e8b514
|
|
| BLAKE2b-256 |
7b070e082cb62f4545a8fc8c13b138c0094b2d379896288da595a9c37c5099a1
|
Provenance
The following attestation bundles were made for growatt_public_api-2025.8.17.tar.gz:
Publisher:
pypi_publish.yaml on timohencken/GrowattPublicApiPy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
growatt_public_api-2025.8.17.tar.gz -
Subject digest:
641fcb350b279b73f31149ae2a591bbdbe366ba2051acb19031803b2605d5452 - Sigstore transparency entry: 404740550
- Sigstore integration time:
-
Permalink:
timohencken/GrowattPublicApiPy@48eccb5f5f840012e47b4238c55f3233d2787968 -
Branch / Tag:
refs/tags/2025.08.17 - Owner: https://github.com/timohencken
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi_publish.yaml@48eccb5f5f840012e47b4238c55f3233d2787968 -
Trigger Event:
release
-
Statement type:
File details
Details for the file growatt_public_api-2025.8.17-py3-none-any.whl.
File metadata
- Download URL: growatt_public_api-2025.8.17-py3-none-any.whl
- Upload date:
- Size: 269.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0d86a64f35378de1314881e901cf401672b4b2d7b110a26f411791b2e5443076
|
|
| MD5 |
5b08c29ec8261a053f5d11ff6a2b0388
|
|
| BLAKE2b-256 |
914c31f7c7815c0ae716d1ccc73c7275c818dc283515a5ce41d44398810abf1c
|
Provenance
The following attestation bundles were made for growatt_public_api-2025.8.17-py3-none-any.whl:
Publisher:
pypi_publish.yaml on timohencken/GrowattPublicApiPy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
growatt_public_api-2025.8.17-py3-none-any.whl -
Subject digest:
0d86a64f35378de1314881e901cf401672b4b2d7b110a26f411791b2e5443076 - Sigstore transparency entry: 404740556
- Sigstore integration time:
-
Permalink:
timohencken/GrowattPublicApiPy@48eccb5f5f840012e47b4238c55f3233d2787968 -
Branch / Tag:
refs/tags/2025.08.17 - Owner: https://github.com/timohencken
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi_publish.yaml@48eccb5f5f840012e47b4238c55f3233d2787968 -
Trigger Event:
release
-
Statement type: