Screenshot analysis quickstart
Build a complete local workflow: exchange a launch token, capture a window, stream an answer and clean up.
Before you start
This walkthrough assumes OpenSS is already running and that the local launch flow has provided a one-time launch token. The token is intentionally not generated by this documentation or by a remote service.
openss gui --no-open
# Copy the local URL printed by OpenSS, then keep this process running.Set local variables
BASE_URL="http://127.0.0.1:PORT"
LAUNCH_TOKEN="the-token-from-the-local-launch-flow"
curl --fail-with-body "$BASE_URL/api/version"Exchange the launch token
The version check is public only in the narrow sense that it does not require a session. The exchange endpoint accepts the launch token once and returns a session token. Do not put either token in source control, logs or a URL you share.
SESSION_TOKEN=$(curl --fail-with-body -sS \
-X POST "$BASE_URL/api/session/exchange" \
-H "Content-Type: application/json" \
-d "{\"launchToken\":\"$LAUNCH_TOKEN\"}" \
| jq -r .sessionToken)
export BASE_URL SESSION_TOKENCapture a supported window
The capture service runs locally and returns OCR plus a temporary ID. Use target values such as chrome, powerpoint or word when you want deterministic selection; omit target to let the local capture rules decide. fullSlide applies to PowerPoint slide-show capture.
CAPTURE=$(curl --fail-with-body -sS \n -X POST "$BASE_URL/api/screenshots/capture" \n -H "X-OpenSS-Session: $SESSION_TOKEN" \n -H "Content-Type: application/json" \n -d "{\"target\":\"chrome\",\"fullSlide\":false}")\n\nSCREENSHOT_ID=$(jq -r .screenshotId <<< "$CAPTURE")\njq . <<< "$CAPTURE"Stream the analysis
The request body uses source: capture to tell the engine that a screenshot is required. The response is an SSE stream, even though the request method is POST. Each data line contains one JSON object.
curl --no-buffer --fail-with-body -sS \
-X POST "$BASE_URL/api/chat/stream" \
-H "X-OpenSS-Session: $SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"source\":\"capture\",\"screenshotId\":\"$SCREENSHOT_ID\",\"message\":\"Summarise the important information and list the next actions.\"}"Delete the temporary capture
curl --fail-with-body -sS \
-X DELETE "$BASE_URL/api/screenshots/$SCREENSHOT_ID" \
-H "X-OpenSS-Session: $SESSION_TOKEN"
# Expected response
{"deleted":true}The same flow in Python
import json
import os
import requests
base_url = os.environ["OPENSS_BASE_URL"].rstrip("/")
launch_token = os.environ["OPENSS_LAUNCH_TOKEN"]
version = requests.get(base_url + "/api/version", timeout=5)
version.raise_for_status()
exchange = requests.post(
base_url + "/api/session/exchange",
json={"launchToken": launch_token},
timeout=5,
)
exchange.raise_for_status()
session = exchange.json()["sessionToken"]
headers = {"X-OpenSS-Session": session}
capture = requests.post(
base_url + "/api/screenshots/capture",
headers=headers,
json={"target": "chrome", "fullSlide": False},
timeout=60,
)
capture.raise_for_status()
screenshot_id = capture.json()["screenshotId"]
try:
with requests.post(
base_url + "/api/chat/stream",
headers=headers,
json={
"source": "capture",
"screenshotId": screenshot_id,
"message": "Summarise the important information and list the next actions.",
},
stream=True,
timeout=120,
) as response:
response.raise_for_status()
for line in response.iter_lines(decode_unicode=True):
if not line or not line.startswith("data: "):
continue
event = json.loads(line[6:])
if "delta" in event:
print(event["delta"], end="", flush=True)
elif event.get("done"):
print()
elif "error" in event:
raise RuntimeError(event["error"])
finally:
requests.delete(
base_url + "/api/screenshots/" + screenshot_id,
headers=headers,
timeout=5,
).raise_for_status()OpenSS/src/openss/gui/server.py and schemas.py.