arccos-api
Unofficial Python client and CLI for the Arccos Golf platform.
Arccos provides no public API. This library gives you read-only programmatic access to your own golf data — rounds, handicap, club distances, pace of play, and more.
Unofficial. Not affiliated with Arccos Golf LLC. Use with your own account only. Respect their servers (no aggressive polling).
Read-only by design. This client only sends
GETrequests to the Arccos data API. It cannot create, edit, or delete rounds, shots, clubs, courses, or account data. Authentication necessarily sendsPOSTrequests to the separate Arccos authentication service to log in and refresh tokens; those requests only obtain credentials and do not modify golf data.
Installation
Install the arccos-api distribution from PyPI:
pip install arccos-api
Or install the CLI with Homebrew:
brew install pfrederiksen/tap/arccos-api
Or install from source:
git clone https://github.com/pfrederiksen/arccos-api.git
cd arccos-api
pip install -e .
Requires Python >= 3.11. Dependencies: requests, click, rich.
CLI
Quick start
arccos login # authenticate and save credentials
arccos rounds # your recent rounds
arccos handicap # handicap breakdown
arccos clubs # smart club distances
Commands
| Command | Description |
|---|---|
arccos login |
Authenticate and cache credentials to ~/.arccos_creds.json |
arccos rounds |
List recent rounds with date, score, +/-, course name |
arccos round <id> |
Hole-by-hole detail (score, putts, FIR, GIR) with totals |
arccos handicap |
Handicap breakdown by category (overall, driving, approach, etc.) |
arccos clubs |
Smart club distances with make/model, range, and shot count |
arccos bests |
All-time personal bests (lowest score, longest drive, etc.) |
arccos overview |
Performance summary — scoring avg + handicap breakdown |
arccos scoring |
Scoring trend with visual bar chart |
arccos compare <a> <b> |
Side-by-side hole-by-hole round comparison |
arccos courses |
List courses you've played (or --search to filter) |
arccos pace |
Pace of play analysis by course (color-coded) |
arccos stats |
Strokes gained analysis (defaults to latest round) |
arccos stats --dashboard |
Strokes gained analysis from the current dashboard endpoint |
arccos tour-analytics |
Tour analytics summary/facet data |
arccos trends |
Handicap trend chart over recent rounds |
arccos club-shots <id> |
Shot history for a specific club |
arccos shot-dispersion [id] |
Shot dispersion for the bag or a specific club |
arccos up-and-down |
Scramble / strokes-to-get-down stats |
arccos hole-image <course> <hole> |
Hole feature metadata and dashboard image URLs |
arccos export |
Export rounds to JSON, CSV, or NDJSON (--detail for hole data) |
arccos completions <shell> |
Generate bash/zsh/fish completion script |
arccos logout |
Clear cached credentials |
Every command supports --json for raw JSON output and --help for usage info.
Usage examples
# Rounds
arccos rounds # last 20 rounds (with +/- and course names)
arccos rounds -n 50 # last 50
arccos rounds --after 2025-01-01 # filter by date
arccos rounds --course "pebble" # filter by course name (substring)
arccos rounds --json # raw JSON
# Round detail
arccos round 12345678 # hole-by-hole breakdown
# Handicap
arccos handicap # category breakdown
arccos handicap --history # revision history
# Club distances
arccos clubs # active clubs with make/model
arccos clubs --after 2025-01-01 # distances from this year only
# Performance
arccos bests # all-time personal bests
arccos overview # scoring avg + handicap breakdown
arccos scoring # scoring trend with bar chart
arccos stats --dashboard # dashboard SGA, same endpoint as web app
arccos stats --dashboard --latest # dashboard SGA for your latest round
arccos trends # handicap trend chart
arccos up-and-down # scramble stats
arccos tour-analytics --facet driving # tour analytics by facet
arccos tour-analytics --summary # tour analytics summary
# Compare rounds
arccos compare 12345678 12345679 # side-by-side hole comparison
# Courses
arccos courses # all courses played
arccos courses --search "torrey" # filter by name or city
# Club detail
arccos club-shots 1 # shot history for club ID 1
arccos shot-dispersion # bag-level dispersion data
arccos shot-dispersion 1 --json # raw dispersion for club ID 1
# Hole imagery metadata
arccos hole-image 10769 7 -v 11 # image + metadata URLs and hole features
# Shell completions
eval "$(arccos completions bash)" # enable tab completion
eval "$(arccos completions zsh)" # for zsh
# Pace of play
arccos pace # all rounds, slowest courses first
arccos pace -n 20 # last 20 rounds only
# Export
arccos export -f csv -o rounds.csv # export to CSV file
arccos export --detail # include hole-by-hole data
arccos export -f json # dump JSON to stdout
arccos export -f ndjson # newline-delimited JSON
Example output
$ arccos clubs
Smart Club Distances
╭──────┬──────────────────┬───────┬─────────┬──────────┬───────╮
│ Club │ Model │ Smart │ Longest │ Range │ Shots │
├──────┼──────────────────┼───────┼─────────┼──────────┼───────┤
│ Dr │ Example Driver │ 252y │ 291y │ 245–263y │ 312 │
│ 3w │ Example Fairway │ 228y │ 248y │ 220–235y │ 87 │
│ 5w │ Example Fairway │ 208y │ 231y │ 200–215y │ 143 │
│ 4h │ Example Hybrid │ 195y │ 214y │ 188–202y │ 61 │
│ 6i │ Example Iron │ 172y │ 190y │ 165–179y │ 94 │
│ 7i │ Example Iron │ 160y │ 178y │ 153–167y │ 118 │
│ 8i │ Example Iron │ 148y │ 165y │ 141–155y │ 105 │
│ 9i │ Example Iron │ 136y │ 152y │ 130–142y │ 97 │
│ Pw │ Example Wedge │ 124y │ 140y │ 118–130y │ 82 │
│ 50 │ Vokey SM10 │ 108y │ 125y │ 102–114y │ 76 │
│ 54 │ Vokey SM10 │ 88y │ 105y │ 82–94y │ 201 │
│ 58 │ Vokey SM10 │ 64y │ 88y │ 58–70y │ 168 │
╰──────┴──────────────────┴───────┴─────────┴──────────┴───────╯
$ arccos round 12345678
╭─── Round 12345678 ────╮
│ Date: 2026-01-15 │
│ Course: Example GC │
│ Score: 79 (+7) │
│ Holes: 18 │
╰───────────────────────╯
Hole-by-Hole
╭──────┬───────┬───────┬─────┬─────╮
│ Hole │ Score │ Putts │ FIR │ GIR │
├──────┼───────┼───────┼─────┼─────┤
│ 1 │ 4 │ 2 │ T │ T │
│ 2 │ 5 │ 2 │ F │ F │
│ 3 │ 3 │ 1 │ │ T │
│ ... │ ... │ ... │ ... │ ... │
├──────┼───────┼───────┼─────┼─────┤
│ Tot │ 79 │ 31 │ │ │
╰──────┴───────┴───────┴─────┴─────╯
$ arccos handicap
Handicap Breakdown
╭────────────┬───────╮
│ Category │ HCP │
├────────────┼───────┤
│ Overall │ -12.4 │
│ Driving │ -15.1 │
│ Approach │ -18.7 │
│ Short Game │ -14.3 │
│ Putting │ -6.2 │
╰────────────┴───────╯
$ arccos pace -n 10
Pace of Play — 10 rounds across 6 courses Overall avg: 4h 22m
By Course (slowest first)
╭───┬──────────┬───────────────────────┬────────╮
│ │ Avg Time │ Course │ Rounds │
├───┼──────────┼───────────────────────┼────────┤
│ ● │ 5h 10m │ Example Golf Club A │ 2 │
│ ● │ 4h 45m │ Example Golf Club B │ 3 │
│ ● │ 3h 50m │ Example Golf Club C │ 2 │
│ ● │ 3h 35m │ Chambers Bay │ 1 │
╰───┴──────────┴───────────────────────┴────────╯
Environment variables
Skip the login prompt by setting:
export ARCCOS_EMAIL="you@example.com"
export ARCCOS_PASSWORD="your_password"
arccos rounds
Other environment variables:
export ARCCOS_TIMEOUT=30 # request timeout in seconds (default: 15)
export ARCCOS_LOG_LEVEL=DEBUG # enable debug logging (DEBUG, INFO, WARNING)
Security note: Environment variables may be visible in process listings (
ps) and shell history. Preferarccos loginfor interactive use.
Python Library
from arccos import ArccosClient
client = ArccosClient(email="you@example.com", password="your_password")
# Credentials cached in ~/.arccos_creds.json. Auto-refreshes silently.
# Rounds
rounds = client.rounds.list(limit=10)
for r in rounds:
print(f"{r['startTime'][:10]} score={r['noOfShots']} {r.get('courseName', '')}")
# Round detail (includes embedded hole-by-hole data)
rd = client.rounds.get(rounds[0]["roundId"])
for hole in rd["holes"]:
print(f" Hole {hole['holeId']}: {hole['noOfShots']} shots, {hole['putts']} putts")
# Handicap breakdown
hcp = client.handicap.current()
print(f"Overall: {hcp['userHcp']:.1f}")
print(f"Driving: {hcp['driveHcp']:.1f}")
# Club distances (returns clubId as bag slot — see bag API for name mapping)
for club in client.clubs.smart_distances():
dist = club["smartDistance"]["distance"]
print(f" Club {club['clubId']}: {dist:.0f}y")
# Bag configuration (maps clubId → clubType + make/model)
profile = client.profile()
bag = client.clubs.bag(str(profile["bagId"]))
for club in bag["clubs"]:
if club.get("isDeleted") != "T":
print(f" {club['clubMakeOther']} {club['clubModelOther']}")
# Current dashboard club/SGA analytics endpoints
club_inventory = client.clubs.list()
shot_dispersion = client.clubs.shot_dispersion()
dashboard_sga = client.stats.dashboard_analysis(goal_hcp=5, no_of_rounds=20)
player_profile = client.stats.player_profile()
tour_summary = client.stats.tour_analytics_summary()
# Course / hole imagery metadata
hole_features = client.courses.hole_features(10769, 7, version=11)
image_url = client.courses.hole_image_url(10769, 7, 11, "2026-07")
metadata_url = client.courses.hole_metadata_url(10769, 7, 11, "2026-07")
# Courses played
for course in client.courses.played():
print(f" {course.get('name', course['courseId'])}")
# Pace of play analysis
pace = client.rounds.pace_of_play()
print(f"Overall avg: {pace['overall_avg_display']}")
for c in pace["course_averages"][:5]:
print(f" {c['avg_display']} {c['course']}")
# Personal bests
bests = client.stats.personal_bests()
# Iterate ALL rounds (auto-pagination)
for r in client.rounds.iter_all():
print(r["roundId"], r["noOfShots"])
# Course search
results = client.courses.search("Example Golf Club")
API Reference
Full OpenAPI 3.1 spec: docs/openapi.yaml
Authentication
All auth calls go to https://authentication.arccosgolf.com.
These are the only non-GET Arccos interactions in this project. They obtain an access key and JWT; they do not write golf or account data.
| Step | Endpoint | Body | Returns |
|---|---|---|---|
| 1. Get access key | POST /accessKeys |
{"email", "password", "signedInByFacebook": "F"} |
{"userId", "accessKey", "secret"} |
| 2. Get JWT | POST /tokens |
{"userId", "accessKey"} |
{"userId", "token"} |
The JWT expires in ~3 hours. The accessKey is valid for ~180 days. Refresh by calling POST /tokens again.
Endpoints
All data calls go to https://api.arccosgolf.com with Authorization: Bearer <token>.
The data client enforces GET only and exposes no POST, PUT, PATCH, or DELETE methods.
| Resource | Method | Path |
|---|---|---|
| User profile | GET | /users/{userId} (includes bagId, bags[]) |
| User details | GET | /users/{userId}/details |
| Bag / clubs | GET | /users/{userId}/bags/{bagId} (club config with make/model) |
| Club inventory | GET | /v6/users/{userId}/clubs |
| Rounds | GET | /users/{userId}/rounds?offSet=0&limit=200&roundType=flagship |
| Round detail | GET | /users/{userId}/rounds/{roundId} (includes holes[] with shots[]) |
| Handicap | GET | /users/{userId}/handicaps/latest |
| Handicap history | GET | /users/{userId}/handicaps?rounds=20 |
| Smart distances | GET | /v4/clubs/user/{userId}/smart-distances |
| Shot dispersion | GET | /v3/user/{userId}/clubs/dispersion |
| Club shot dispersion | GET | /v3/user/{userId}/clubs/{clubId}/dispersion |
| Courses played | GET | /users/{userId}/coursesPlayed |
| Course metadata | GET | /courses/{courseId}?courseVersion=1 |
| Hole feature metadata | GET | /courses/{courseId}/holes/{holeId}?courseVersion=1 |
| Course search | GET | /v2/courses?search={query} |
| Club shots | GET | /users/{userId}/bags/{bagId}/clubs/{clubId}/shots |
| Dashboard SGA | GET | /sga/getDashboardAnalysis/{userId} |
| SGA player profile | GET | /sga/playerProfile/{userId} |
| Tour analytics | GET | /users/{userId}/tourAnalytics |
| Tour analytics summary | GET | /users/{userId}/tourAnalyticsSummary |
| Tour analytics ranked | GET | /users/{userId}/tourAnalyticsRanked |
| Personal bests | GET | /users/{userId}/personalBests?tags=allTimeBest |
| Strokes to get down | GET | /v2/sga/strokes-to-get-down |
Key data structures
Round (from GET /users/{id}/rounds/{roundId}):
{
"roundId": 12345678,
"courseId": 12450,
"courseVersion": 4,
"startTime": "2026-01-15T15:30:00.000000Z",
"endTime": "2026-01-15T20:15:00.000000Z",
"noOfShots": 79,
"noOfHoles": 18,
"holes": [
{
"holeId": 1, "noOfShots": 4, "putts": 2,
"isGir": "T", "isFairWay": "T",
"shots": [{"clubId": 1, "clubType": 1, "distance": 255.0}]
}
]
}
Smart distance (from GET /v4/clubs/user/{id}/smart-distances):
{
"clubId": 1,
"smartDistance": {"distance": 252.3, "unit": "yd"},
"longest": {"distance": 291.0, "unit": "yd"},
"range": {"low": 245.0, "high": 263.0, "unit": "yd"},
"usage": {"count": 312}
}
Bag club (from GET /users/{id}/bags/{bagId}):
{
"clubId": 1, "clubType": 1,
"clubMakeOther": "Example", "clubModelOther": "Model 1",
"isDeleted": "F"
}
clubIdis a user-specific bag slot. Resolve to a display name via: bag'sclubType→ standard name (1=Dr, 2=3w, 3=5w, 5=4i, ..., 11=Pw, 12=Putter, 43=Aw, 53=56°).
Development
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
pytest # tests with coverage (87%+, 173 tests)
ruff check . # lint
mypy arccos/ # type check
Coverage report: htmlcov/index.html. Minimum threshold: 80% (configured in pyproject.toml).
Current suite: 173 tests.
Security
- Data access is read-only: the client only sends
GETrequests toapi.arccosgolf.com. The onlyPOSTrequests are the required login/token-refresh calls toauthentication.arccosgolf.com; no golf data is created, changed, or deleted. - Credentials are cached in
~/.arccos_creds.json(mode0600— owner-only read/write). The file contains your access key (~180-day validity) and JWT token. Keep it safe. - All API communication uses HTTPS with TLS certificate verification.
arccos logoutremoves the local credential file but does not revoke server-side tokens. If you suspect your credentials were compromised, change your Arccos password.- The export command restricts output paths to your home directory or current working directory.
- Security issues should be reported privately as described in
SECURITY.md.
Disclaimer
Not affiliated with, endorsed by, or connected to Arccos Golf LLC. Use your own account credentials only. This project is for personal data access and research.
MIT License.
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 arccos_api-0.5.1.tar.gz.
File metadata
- Download URL: arccos_api-0.5.1.tar.gz
- Upload date:
- Size: 59.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f61f6939b6545a10e72b385a04051e5a3471441cfafbb8b6cf97583a3e313ab9
|
|
| MD5 |
529b1ff84f55e1c50126670775a35988
|
|
| BLAKE2b-256 |
87b9ebf6d99ef86031c481c8cc6cb06f2ef37f498b0e4a54eb2f494212242994
|
File details
Details for the file arccos_api-0.5.1-py3-none-any.whl.
File metadata
- Download URL: arccos_api-0.5.1-py3-none-any.whl
- Upload date:
- Size: 47.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
24c098f4c5a0664e343404c0e62164dfccfb2cdef004673917ca0f853d68118a
|
|
| MD5 |
c63db8bc4509940567d52db0f065e21d
|
|
| BLAKE2b-256 |
7598c57b5b183512e5e05c8c0984ddecd196e27e2fead07995af910b13d8194a
|