{"id":639,"library":"gspread","title":"gspread - Google Spreadsheets Python API","description":"gspread is a Python API for Google Sheets, providing a simple interface to interact with spreadsheets. It supports Google Sheets API v4 and offers features like opening spreadsheets by title, key or URL, reading, writing, and formatting cell ranges, sharing, access control, and batching updates. It is currently at version 6.2.1 and is actively maintained with frequent minor and patch releases.","status":"active","version":"6.2.1","language":"python","source_language":"en","source_url":"https://github.com/burnash/gspread","tags":["google-sheets","spreadsheets","automation","api","google-api"],"install":[{"cmd":"pip install gspread","lang":"bash","label":"Install latest version"}],"dependencies":[{"reason":"Requires Python >=3.8.","package":"python","optional":false},{"reason":"Used for various authentication methods (service account, OAuth).","package":"google-auth","optional":false},{"reason":"Used for HTTP communication with the Google Sheets API.","package":"requests","optional":false}],"imports":[{"note":"Main library import for accessing the Google Sheets API.","symbol":"gspread","correct":"import gspread"},{"note":"The `service_account()` method is the modern and recommended way for bot/script authentication using a service account JSON key file. `authorize()` is for OAuth2 credentials via `google.auth.credentials.Credentials` objects.","wrong":"gc = gspread.authorize(credentials)","symbol":"gspread.service_account","correct":"import gspread\ngc = gspread.service_account()"},{"note":"Used for end-user authentication, often involving an interactive browser flow.","symbol":"gspread.oauth","correct":"import gspread\ngc = gspread.oauth()"},{"note":"Authenticates using an API key, suitable for accessing public spreadsheets only.","symbol":"gspread.api_key","correct":"import gspread\ngc = gspread.api_key('YOUR_API_KEY')"},{"note":"Catches API-specific errors (e.g., rate limits, invalid requests) from the Google Sheets API.","symbol":"gspread.exceptions.APIError","correct":"from gspread.exceptions import APIError"}],"quickstart":{"code":"import gspread\nimport os\n\n# Ensure your service account key file path is set as an environment variable\n# or replace with the actual path.\n# For example: export GSPREAD_SERVICE_ACCOUNT_KEYFILE=\"./path/to/your/service_account.json\"\n\nSERVICE_ACCOUNT_KEYFILE = os.environ.get(\n    'GSPREAD_SERVICE_ACCOUNT_KEYFILE',\n    './path/to/your/service_account.json' # Placeholder, replace or use env var\n)\n\ntry:\n    # Authenticate using a service account\n    # Make sure to share your Google Sheet with the service account email address.\n    gc = gspread.service_account(filename=SERVICE_ACCOUNT_KEYFILE)\n\n    # Open a spreadsheet by its title\n    spreadsheet_title = \"My Test Spreadsheet\"\n    sh = gc.open(spreadsheet_title)\n\n    # Select the first worksheet\n    wks = sh.sheet1\n\n    print(f\"Successfully opened spreadsheet: {sh.title}\")\n    print(f\"First worksheet title: {wks.title}\")\n\n    # Read a single cell value\n    cell_a1 = wks.acell('A1').value\n    print(f\"Value in A1: {cell_a1}\")\n\n    # Update a single cell\n    wks.update_acell('B1', 'Hello gspread!')\n    print(\"Updated cell B1.\")\n\n    # Update a range of cells (using v6 syntax with 2D array and named args)\n    data_to_write = [['Name', 'Age'], ['Alice', 30], ['Bob', 24]]\n    wks.update(values=data_to_write, range_name='A3')\n    print(\"Updated range A3:B5.\")\n\n    # Get all values from the worksheet as a list of lists\n    all_values = wks.get_all_values()\n    print(\"\\nAll values in the worksheet:\")\n    for row in all_values:\n        print(row)\n\nexcept FileNotFoundError:\n    print(f\"Error: Service account key file not found at {SERVICE_ACCOUNT_KEYFILE}. \")\n    print(\"Please ensure the file exists and the path is correct.\")\nexcept gspread.exceptions.SpreadsheetNotFound:\n    print(f\"Error: Spreadsheet '{spreadsheet_title}' not found or not shared with the service account.\")\n    print(\"Ensure the spreadsheet name is correct and shared with the client_email from your service account JSON.\")\nexcept gspread.exceptions.APIError as e:\n    print(f\"Google Sheets API Error: {e}\")\n    print(\"This might be a rate limit issue or incorrect API permissions.\")\nexcept Exception as e:\n    print(f\"An unexpected error occurred: {e}\")\n","lang":"python","description":"This quickstart demonstrates how to authenticate with gspread using a service account, open a spreadsheet, read a cell, and update cells. Ensure you have enabled the Google Drive API and Google Sheets API in your Google Cloud project and shared your spreadsheet with the service account's email. The example uses an environment variable for the keyfile path for better security and flexibility."},"warnings":[{"fix":"Upgrade your Python environment to 3.8 or a later version.","message":"Python 3.7 End-of-Life: gspread v6+ officially drops support for Python 3.7. Your project must use Python 3.8 or newer.","severity":"breaking","affected_versions":"6.0.0 and later"},{"fix":"Either swap the arguments (`worksheet.update(values, range_name)`) or, preferably, use named arguments (`worksheet.update(values=..., range_name=...)`) for clarity and forward compatibility. Ensure `values` is always a list of lists.","message":"Worksheet.update() arguments swapped and value format changed. The `values` and `range_name` arguments are swapped. Additionally, `values` must now be a 2D array (list of lists), not a simple list.","severity":"breaking","affected_versions":"6.0.0 and later"},{"fix":"Use `worksheet.get_all_records()` to retrieve all records or fetch specific ranges with `worksheet.get()` and process them using `gspread.utils.to_records(header, cells)` if partial records are needed.","message":"Worksheet.get_records() method removed. This method is no longer available in v6.","severity":"breaking","affected_versions":"6.0.0 and later"},{"fix":"Convert color dictionaries to hexadecimal strings (e.g., `{'red': 1, 'green': 0.5, 'blue': 1}` to `\"#FF7FFF\"`). A utility function `gspread.utils.convert_colors_to_hex_value()` is available for compatibility.","message":"Color representation for formatting changed from dictionary to hexadecimal strings.","severity":"breaking","affected_versions":"6.0.0 and later"},{"fix":"You *must* share the target Google Sheet with the `client_email` address found in your service account's JSON key file. Treat it like sharing with any other Google user.","message":"SpreadsheetNotFound error (or similar access issues) when using a Service Account.","severity":"gotcha","affected_versions":"All versions"},{"fix":"The Sheets API has limits (e.g., 100 requests/100 seconds per project, 60 requests/60 seconds per user). Minimize API calls by using batch operations (`update()`, `batch_update()`, `get_all_values()`, `batch_get()`) instead of individual cell/row operations in loops. Consider using `gspread.http_client.BackOffHTTPClient` for automatic retry with exponential back-off.","message":"Google Sheets API rate limits can lead to `gspread.exceptions.APIError: 429 RESOURCE_EXHAUSTED`.","severity":"gotcha","affected_versions":"All versions"},{"fix":"This usually means the `authorized_user.json` credentials have expired. Delete the `authorized_user.json` file (located in `~/.config/gspread/` on Linux/macOS or `%APPDATA%\\gspread\\` on Windows) and re-run your code to initiate a new authentication flow.","message":"OAuth Client ID authentication sometimes results in `google.auth.exceptions.RefreshError: invalid_grant: Token has been expired or revoked.`","severity":"gotcha","affected_versions":"All versions using OAuth Client ID"},{"fix":"Ensure that the path to your service account JSON key file (e.g., `./path/to/your/service_account.json`) is correct and that the file exists at that location. Double-check file permissions if the path is correct but the file is inaccessible by the running process. The path is typically provided during client authorization (e.g., `gspread.service_account(filename='path/to/key.json')`).","message":"Service account key file not found. This error indicates that the gspread client could not locate the specified service account JSON key file, preventing authentication.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Verify that the JSON key file for your service account exists at the path you are providing (e.g., to `gspread.service_account(filename='path/to/key.json')`) or that the `GSPREAD_SERVICE_ACCOUNT_PATH` environment variable points to a valid file. Double-check the filename and directory path for typos and correct permissions.","message":"Service account key file not found at the specified path during initialization.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-05-12T17:06:00.394Z","next_check":"2026-06-26T00:00:00.000Z","problems":[{"fix":"Delete the `authorized_user.json` file (on Windows: `%APPDATA%\\gspread\\`, on other systems: `~/.config/gspread/credentials.json`) and re-run your code to initiate a new authentication flow.","cause":"This error typically means your OAuth 2.0 client credentials (specifically the refresh token) have expired, been revoked, or are otherwise invalid, often due to an outdated `authorized_user.json` file or the user revoking access from their Google account.","error":"google.auth.exceptions.RefreshError: ('invalid_grant: Token has been expired or revoked.', {'error': 'invalid_grant', 'error_description': 'Token has been expired or revoked.'})"},{"fix":"Share the Google Sheet directly with the service account's email address (found in your service account JSON key file) and grant it editor permissions, or ensure the authenticated user has sufficient access to the sheet.","cause":"This error occurs when the service account or authenticated user lacks the necessary permissions (e.g., editor access) to interact with the target Google Sheet or Drive API.","error":"gspread.exceptions.APIError: {'code': 403, 'message': 'The caller does not have permission', 'status': 'PERMISSION_DENIED'}"},{"fix":"Double-check the spreadsheet title, key, or URL for typos, and ensure the Google Sheet is shared with the service account's email address.","cause":"The specified Google Sheet could not be found, often due to an incorrect spreadsheet title, key, or URL, or because the service account/user does not have access to the spreadsheet.","error":"gspread.exceptions.SpreadsheetNotFound: {'code': 404, 'message': 'Requested entity was not found.'}"},{"fix":"Upgrade `gspread` to the latest version using `pip install --upgrade gspread` to access the newer API methods.","cause":"This error usually indicates that the `gspread` library version is outdated, and the `update()` method (or similar methods like `insert_rows()`) that you are trying to use was not available in that older version.","error":"AttributeError: 'Worksheet' object has no attribute 'update'"}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":80,"quickstart_tag":"verified","pypi_latest":"6.2.1","install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":1.26,"mem_mb":17.3,"disk_size":"44.7M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":1.21,"mem_mb":16.9,"disk_size":"43.6M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":3.8,"import_time_s":0.92,"mem_mb":17.3,"disk_size":"45M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.92,"mem_mb":16.9,"disk_size":"44M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":1.54,"mem_mb":19.6,"disk_size":"48.1M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":1.72,"mem_mb":19.3,"disk_size":"47.0M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":3.6,"import_time_s":1.4,"mem_mb":19.6,"disk_size":"49M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":1.31,"mem_mb":19.3,"disk_size":"47M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":1.57,"mem_mb":19.4,"disk_size":"39.7M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":1.71,"mem_mb":19.1,"disk_size":"38.5M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":3.2,"import_time_s":1.66,"mem_mb":19.4,"disk_size":"40M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":1.63,"mem_mb":19.1,"disk_size":"39M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":1.63,"mem_mb":20.4,"disk_size":"39.4M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":1.64,"mem_mb":20.1,"disk_size":"38.2M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":3.3,"import_time_s":1.63,"mem_mb":20.4,"disk_size":"40M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":1.67,"mem_mb":20.1,"disk_size":"39M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":1.18,"mem_mb":17.1,"disk_size":"44.7M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":1.12,"mem_mb":16.9,"disk_size":"43.7M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":4.5,"import_time_s":1.1,"mem_mb":17.1,"disk_size":"45M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.98,"mem_mb":16.9,"disk_size":"44M"}]},"quickstart_checks":{"last_tested":"2026-04-24","tag":"verified","tag_description":"quickstart runs on critical runtimes, recently tested","results":[{"runtime":"python:3.10-alpine","exit_code":0},{"runtime":"python:3.10-slim","exit_code":0},{"runtime":"python:3.11-alpine","exit_code":0},{"runtime":"python:3.11-slim","exit_code":0},{"runtime":"python:3.12-alpine","exit_code":0},{"runtime":"python:3.12-slim","exit_code":0},{"runtime":"python:3.13-alpine","exit_code":0},{"runtime":"python:3.13-slim","exit_code":0},{"runtime":"python:3.9-alpine","exit_code":0},{"runtime":"python:3.9-slim","exit_code":0}]}}