History¶
0.20.2 (2025-08-19)¶
Handle empty user when pretty-printing
IdentificationobjectsClientSessionargumentsratelimit_pathandlock_pathwill now apply to the separate rate-limiter used for/projects/{id}
0.20.1 (2025-01-18)¶
Fix
AttributeErrorwhen initializingObservation.taxonwith aTaxonobject
0.20.0 (2025-01-02)¶
⚠️ Deprecations & Removals¶
Drop support for python 3.7
Models¶
Add
User.annotated_observations_countfieldAdd
root_idfilter totaxon.make_tree()to explicitly set the root taxon instead of determining it automaticallyFix
taxon.make_tree()rank filtering to allow skipping any number of rank levelsFix
taxon.make_tree()rank filtering to handle all available ranks filtered outUpdate
taxon.make_tree()to return copies of original taxon objects instead of modifying them in-placeUpdate
Taxon.flatten(hide_root=True)to only hide the root taxon if it was automatically inserted bymake_tree()Add shortcut properties to
Taxonfor ancestors of common ranks:Taxon.kingdom,phylum,class_(note the_; ‘class’ is a reserved keyword),order,family,genusUpdate
Observation.taxon.ancestorsbased on identification data, if available
Rate limits, timeouts, and error handling¶
Increase default request timeout from 10 to 20 seconds
Add
validate_token()function to manually check if an access token is validSupport rate limits less than one request per second (example:
ClientSession(per_second=0.5))Add error handling for file uploads over 20MB (not accepted by API)
Allow setting lockfile path used for multiprocess rate limiting (example:
ClientSession(lock_path='/tmp/pyinat.lock'))
Bugfixes¶
Fix
KeyErrorwhen usingcreate_observation()in dry-run mode
Other changes¶
Added support for python 3.13
Convert packaging and project config to
uv. This has no impact on users. For developers, see Contributing Guide for details.
0.19.0 (2023-12-12)¶
New Endpoints¶
Added new User endpoint:
get_current_user()Added new Taxon endpoint:
get_life_list_metadata()
Modified Endpoints¶
Add support for searching observations by observation fields, using a new observation_fields param for the following functions:
get_observations()get_observation_histogram()get_observation_identifiers()get_observation_observers()get_observation_popular_field_values()get_observation_species_counts()
Models¶
Observation:
Add
Observation.ident_taxon_idsdynamic property to get all identification taxon IDs (with ancestors)Add
Observation.cumulative_idsdynamic property to calculate agreements/total community identificationsAdd
Applicationmodel forObservation.application(for v2 API)Add
Favemodel forObservation.favesAdd
Flagmodel forObservation.flagsAdd
QualityMetricmodel forObservation.quality_metricsAdd
Soundmodel forObservation.soundsAdd
Votemodel forObservation.votes
Project:
Add
Project.last_post_atdatetime attributeAdd
Project.observation_requirements_updated_atdatetime attribute
Taxon:
Add
make_tree()function to build a tree fromTaxonobjects or aLifeListAdd
pprint_tree()function to print a taxon tree on the consoleAdd
Taxon.flatten()method to return a taxon and its descendants as a flat listFix initialization of
ListedTaxon.place
Other changes¶
Added support for python 3.12
0.18.0 (2023-02-27)¶
⚠️ Deprecations & Removals¶
get_observation()is now deprecated, and will be removed in a future releasePlease use
get_observations()orget_observations_by_id()instead
Remove redundant
Annotation.controlled_attribute_idandcontrolled_value_idattributes (These can still be used as init arguments)
New Endpoints¶
Added new Observation endpoint:
get_observations_by_id()Replaces
get_observationAccepts multiple IDs
Uses a different endpoint (
GET /observations/{id}instead ofGET /observations?id={id})returns full term and value details for annotations
Modified Endpoints¶
Add some undocumented request params to
get_taxa_by_id():localepreferred_place_idall_names
Models¶
Add full mapping of conservation status codes for IUCN, NatureServe, Norma Oficial Mexicana, and other generic codes
Translate
ConservationStatus.status_namebased on status code and authority for more consistent resultsAdd
ConservationStatus.display_namepropertyAdd
Observation.default_photopropertyUse taxon icon as placeholder for
Observation.default_photoif observation has no photosUpdate
Annotationmodel to include controlled term and value details from updatedGET /observations/{id}response formatAdd
Annotation.termandvalueproperties and init arguments for simpler initialization from term and value labels
Sessions¶
Add
cache_controloption toClientSessionto disable using Cache-Control headers for cache expiration (enabled by default)Add
urls_expire_afteroption toClientSessionto update default cache expiration URL patterns
Bugfixes¶
Fix error
413: Payload too largewhen usingadd_project_users()ordelete_project_users()with a project with a large number of rulesFix JWT caching
Fix
ObservationFieldValueconversions fordateanddatetimefieldsFix printing
Annotationobjects withrichFix printing
Observationtables when taxon is missing
Other Changes¶
Added support for python 3.11
All API functions that accept taxonomic rank parameters (
rank,lrank,observation_hrank,etc.) now accept all rank variations that iNaturalist accepts (var,sppsub-species, etc.)Optionally use
ultrajsoninstead of stdlibjson, if installedAdd
loopargument to iNatClient and Paginator classes to allow passing an async event loop to be used for async iterationAdd
Paginator.async_all()method (async, non-blocking version of.all())
0.17.4 (2022-07-11)¶
Use a single data directory instead of separate ‘cache’ and ‘user data’ dirs
Platform-dependent; on Linux, for example, this will be
~/.local/share/pyinaturalist
0.17.3 (2022-06-28)¶
Add retries for requests that return invalid (truncated) JSON
max_retriesandbackoff_factorarguments forClientSessionwill apply to these retries (in addition to other request errors)
0.17.2 (2022-06-12)¶
Handle nested ‘photo’ dictionaries when loading
Taxon.taxon_photosAdd model for
ListedTaxon.list, and handle differences in format between/taxaand/observations/{id}/taxon_summaryMinor fixes and improvements for creating and converting
Observation,Taxon, and other model objects
0.17.1 (2022-05-20)¶
Fix pagination bug causing only the first two pages of results to be returned
Add Photo.uuid, observation_id, and user_id fields (for compatibility with inaturalist-open-data)
Handle errors in ObservationField type conversions
Improve terminal output for nested model objects (like
Observation.taxon,Taxon.ancestors, etc.)If
Taxon.ancestor_idsis missing, populate from eitherancestrystring orancestorobjects, if possible
0.17.0 (2022-05-17)¶
⚠️ Deprecations & Removals¶
Dropped support for python 3.6
New Endpoints¶
Added new Observation endpoint:
get_observation_popular_field_values()
Added new Project endpoint and helper functions:
update_project()add_project_users()delete_project_users()
Modified Endpoints¶
Updated
get_projects_by_id()to allow string values (URL slugs) forproject_idUpdated
get_user_by_id()to allow string values (usernames) foruser_idAdded support for setting timeout for individual API requests (with
timeoutparameter)Added support for setting cache timeout for individual API requests (with
expire_afterparameter)Added support for bypassing the cache for individual API requests (with
refreshparameter)
Authentication¶
Added support for JWT authentication, which will now be used by default
To get an OAuth access token instead of a JWT, call
get_access_token(jwt=False)
Added caching to
get_access_token(). JWTs will be stored in the API response cache and reused until they expire.
Models¶
Remove default values from output when model objects are printed with
richAdd
ControlledTermCountmodel for use with/observations/popular_field_valuesPhoto: AddextandmimetypepropertiesTaxon: Use icon in place ofdefault_photoif missing
Other Changes¶
Add an optional, abbreviated namespace
pyinatas an alias forpyinaturalistUpdated rate limiting with a SQLite-based backend. This adds persistence for rate limit tracking across multiple threads, processes, and/or application restarts. See pyrate-limiter docs for more details.
Add a
clear_cache()function for clearing cached API responsesMisc improvements for response pretty-printing
0.16.0 (2022-02-22)¶
⚠️ Deprecations & Removals¶
Removed
pyinaturalist.user_agentglobal variable and API function keyword args, and recommend setting on session object insteadRemoved
pyinaturalist.DRY_RUN*global variables, and recommend setting in environment variables instead
New Endpoints¶
Added new Taxon endpoint:
get_taxa_map_layers()Added new Message endpoints:
get_messages()get_message_by_id()get_unread_message_count()
Observation Media¶
The following changes apply to upload(), create_observation(), and update_observation():
Added support for uploading observation photo & sound files from URLs
Added support for attaching previously uploaded photos to an observation by photo ID
Other Changes¶
Added support for python 3.10
Fixed
count_only=True/per_page=0to not run full queryDo not error on unrecognized
**kwargs, for cases where the API may accept some additional undocumented parametersAllow overriding default location for API request cache
0.15.0 (2021-09-07)¶
New Endpoints¶
Added new functions for v1 Observation endpoints:
create_observation()update_observation()delete_observation()upload()(uploads both photos and sounds)These are now preferred over the older v0 endpoints
Added new functions for v1 Observation field value endpoints:
set_observation_field()(creates and updates observation field values)delete_observation_field()
Added new function for Observation taxon summary:
get_observation_taxon_summary()Added new functions for Project observation endpoints:
add_project_observation()delete_project_observation()
Modified Endpoints¶
Added a
dry_runargument to all API request functions to dry-run an individual requestAdded a
reverseargument to all paginated API request functions to reverse the sort order
Models¶
Performance¶
Added API request caching with requests-cache
Updated rate-limiting not apply to cached requests
Added custom
ClientSessionclass to configure caching, rate-limiting, retries, and timeouts
Logging¶
Improved logging output for dry-run mode: now shows formatted
PreparedRequestdetails instead ofrequest()keyword argsAdded an
enable_logging()function to optionally show prettier logs withrichUpdated logging to redact all credentials from logged API requests
Other Changes¶
Increased default timeout to 10 seconds to accommodate some longer-running queries
Added
get_interval_ranges()function to help with queries over a series of date/time intervalsFixed bug with
rule_detailsparam forget_projects_by_id()Added more tutorial/example notebooks
0.14.1 (2021-07-21)¶
Added new function for Posts endpoint:
get_posts()Fixed broken
response_formatparameter inv0.get_observations()
0.14.0 (2021-07-14)¶
⚠️ Deprecations & Removals¶
Deprecated
pyinaturalist.rest_apimodule (moved topyinaturalist.v0subpackage)Deprecated
pyinaturalist.node_apimodule (moved topyinaturalist.v1subpackage)Deprecated
get_geojson_observations()(moved to join other observation conversion tools inpyinaturalist-convert)
New Endpoints¶
Added new function for Observation sounds endpoint:
upload_sounds()Added new function for Life list endpoint:
get_observation_taxonomy()
Modified Endpoints¶
Added support for passing a
requests.Sessionobject to all API request functionsAdded a
photosparametercreate_observation()andupdate_observation()to upload photosAdded a
soundsparametercreate_observation()andupdate_observation()to upload soundsRenamed
add_photo_to_observation()toupload_photos()The alias
rest_api.add_photo_to_observation()is still available for backwards-compatibility
Updated
upload_photos()to take accept either a single photo or a list of photos, and return a list of responsesUpdated
upload_sounds()to take accept either a single sound or a list of sounds, and return a list of responsesAdded alias
observed_onforobserved_on_stringincreate_observation()Fixed conversion for datetime parameters in
create_observation()andupdate_observation()Updated all requests to correctly convert
datetimeobjects to stringsMoved API functions into separate modules by API version and resource type.
All can still be imported via
from pyinaturalist import *Added aliases for backwards-compatibility, so imports from
pyinaturalist.rest_apiandpyinaturalist.node_apiwill still work
Models¶
Added data models for all API response types, to support working with typed python objects instead of JSON.
Models:
Comment
ControlledTerm
ControlledTermValue
Annotation
Identification
LifeList
LifeListTaxon
Observation
ObservationField
ObservationFieldValue
Photo
Place
Project
ProjectObservation
ProjectObservationField
ProjectUser
SearchResult
Taxon
ConservationStatus
EstablishmentMeans
TaxonCount
TaxonCounts
User
Model features:
Type conversions
Lazy initialization
Basic formatters
Table formatters
Other Changes¶
Consolidated response formatting into a single
pprint()function (instead of one per resource type)Refactored and reorganized the following internal utility modules (see API docs for details):
convertersdocsformattersrequest_params
Added a default response timeout of 5 seconds
Added an example (
examples/sample_responses.py) containing response JSON, model objects, and tables of every type to experiment withAdded a tutorial notebook (
examples/Tutorial.ipynb)Set up pyinaturalist-notebook to be runnable with Binder
0.13.0 (2021-05-22)¶
⚠️ Deprecations & Removals¶
The following methods are now deprecated. They are still functional, but will raise a
DeprecationWarning, and will be removed in a future release:node_api.get_all_observations()node_api.get_all_observation_species_counts()rest_api.get_all_observation_fields()
Removed
minifyoption fromget_taxa_autocomplete
New Endpoints¶
Added new function for Search endpoint:
search()(combined search for places, projects, taxa, and users)Added new functions for Identifications endpoints:
get_identifications()andget_identifications_by_id()Added new functions for Users endpoints:
get_user_by_id()andget_users_autocomplete()
Modified Endpoints¶
Added undocumented
ident_user_idparameter toget_observations()Added
count_only=Trueas an alias forper_page=0(to get only result counts).Added generic auto-pagination that can apply to any endpoint that supports pagination.
Added
page='all'as a shortcut for auto-paginationThe above changes apply to all functions that support pagination:
node_api.get_identifications()node_api.get_observations()node_api.get_observation_species_counts()node_api.get_observation_observers()node_api.get_observation_identifiers()node_api.get_places_autocomplete()node_api.get_projects()node_api.get_taxa()rest_api.get_observations()rest_api.get_observation_fields()
Updated
rest_api.get_observation_fields()to return a dict with'results'for consistency with other endpoints
Other Changes¶
Added response formatting functions to
pyinaturalist.formattersAll API functions and formatters can now be imported from the top-level package, e.g.
from pyinaturalist import *Published pyinaturalist on conda-forge
Added global rate-limiting to stay within the rates suggested in API Recommended Practices (per second, minute, and day)
Moved
Dockerfileanddocker-compose.ymlto a separate repo (pyinaturalist-notebook) and published on Docker HubPackaging is now handled with Poetry. For users, installation still works the same. For developers, see Contributing Guide for details.
0.12.1 (2021-03-07)¶
Add undocumented
ident_user_idparameter toget_observations()
0.12.0 (2021-02-02)¶
⚠️ Deprecations & Removals¶
Dropped support for python 3.5
Removed request parameters that were deprecated in 0.11
New Endpoints¶
Added new function for Observation Histogram endpoint:
get_observation_histogram()Added new function for Observers endpoint:
get_observation_observers()Added new function for Identifiers endpoint:
get_observation_identifiers()Added new function for Controlled Terms endpoints:
get_controlled_terms()Wraps both
GET /controlled_termsand/controlled_terms/for_taxonendpoints
Modified Endpoints¶
Added conversion from date/time strings to timezone-aware python
datetimeobjects. This applies to the following functions:node_api.get_observation()node_api.get_observations()node_api.get_all_observation()node_api.get_projects()node_api.get_projects_by_id()node_api.get_taxa()node_api.get_taxa_by_id()rest_api.get_observation()rest_api.get_observation_fields()rest_api.get_all_observation_fields()
Added conversion for an additional
locationfield in observation responses
Authentication¶
Added support for providing credentials via environment variables
Added integration with system keyring for credentials storage
Added documentation & examples for authentication options
Other Changes¶
Added a
Dockerfileanddocker-compose.ymlfor a Jupyter notebook containing pyinaturalist + other relevant packagesAdded some more detailed usage examples under
examples/Improved performance for large paginated queries
Fixed bug that dropped request parameter values of
0as if they wereNone
0.11.0 (2020-11-04)¶
⚠️ Deprecations & Removals¶
Dropped support for python 3.4
Using the
paramspositional argument for the handful of functions that used it will raise aDeprecationWarning, but will otherwise still be functional until0.12Using the
search_queryargument forrest_api.get_observation_fields()andrest_api.get_all_observation_fields()will raise aDeprecationWarning, but will otherwise still be functional until0.12
New Endpoints¶
Added new functions for Node API Places endpoints:
get_places_by_id()get_places_nearby()get_places_autocomplete()
Added new functions for Node API Projects endpoints:
get_projects()get_projects_by_id()
Added new function for an additional Node API Observation endpoint:
get_observation_species_counts()get_all_observation_species_counts()
Modified Endpoints¶
Added support for simplified observation field syntax (
observation_fields={id: value}) forcreate_observations()andupdate_observation()Updated
node_api.get_taxa_by_id()to accept multiple IDsUpdated
rest_api.get_observations()with type conversion from strings to floats for response lat/long coordinates. Only applies to JSON response format.Updated
node_api.get_taxa_autocomplete()with optionalmin_rankandmax_rankparameters, for consistency withget_taxa()Renamed
search_queryargument toqto be consistent with API request parametersRenamed
create_observations()tocreate_observation(), as this only supports creating a single observation per call. This is aliased tocreate_observations()for backwards-compatibility, but will raise aDeprecationWarning.
Documentation & Usability¶
Added example response data to docs all endpoints
Added links to official API reference to docs for all endpoints
Added full API request parameters to all API functions, in the form of keyword arguments with type annotations and docstrings
Added complete table of iNaturalist API endpoints and endpoints implemented by pyinaturalist
Added and improved usage examples
Numerous other documentation improvements
Made all API function signatures consistent by taking request params as keyword arguments
Other Changes¶
Added support for python 3.9
Added parameter validation for multiple-choice request parameters
0.10.0 (2020-06-16)¶
New Endpoints¶
Added new Observation endpoint:
rest_api.get_observations(), with 6 additional observation response formats, including GeoJSON, Darwin Core, and others
Modified Endpoints¶
Added
minifyoption tonode_api.get_taxa_autocomplete()
Other Changes¶
Added more info & examples to README for taxa endpoints, and other documentation improvements
Added conversion for all date and datetime parameters to timezone-aware ISO 8601 timestamps
Added a dry-run mode to mock out API requests for testing
Set up pre-release builds for latest development version
0.9.1 (2020-05-26)¶
Bugfix: proper support for boolean and integer list parameters (Issue #17)
0.9.0 (2020-05-06)¶
New Endpoints¶
Added new functions for Node API Taxa endpoints:
node_api.get_taxa()node_api.get_taxa_autocomplete()node_api.get_taxa_by_id()
0.8.0 (2019-07-11)¶
All functions now take an optional
user-agent <https://en.wikipedia.org/wiki/User_agent>_ parameter in order to identify yourself to iNaturalist. If not set,Pyinaturalist/<VERSION>will be used.
0.7.0 (2019-05-08)¶
rest_api.delete_observation()now raisesObservationNotFoundif the observation doesn’t existminor dependencies update for security reasons
0.6.0 (2018-11-15)¶
New function:
rest_api.delete_observation()
0.5.0 (2018-11-05)¶
New function:
node_api.get_observation()
0.4.0 (2018-11-05)¶
create_observation()now raises exceptions in case of errors.
0.3.0 (2018-11-05)¶
update_observation()now raises exceptions in case of errors.
0.2.0 (2018-10-31)¶
Better infrastructure (type annotations, documentation, …)
Dropped support for Python 2.
New function:
update_observation()rest_api.AuthenticationErroris nowexceptions.AuthenticationError
0.1.0 (2018-10-10)¶
First release on PyPI.