State
Persist data between script runs.
Overview
Sometimes your script needs to remember things between runs. Humrun provides a simple key-value store for this purpose.
Common use cases:
- Track the last item processed to avoid duplicates
- Store counters or aggregates
- Remember the previous value to detect changes
- Cache data that's expensive to fetch
Using state
Import the state object and use it like a dictionary:
from state import state
# Get a value (returns None if not set)
last_id = state.get("last_processed_id")
# Set a value
state["last_processed_id"] = "abc123"
Values are stored as strings. For complex data, use JSON:
import json
from state import state
# Store a dict
data = {"count": 42, "items": ["a", "b", "c"]}
state["my_data"] = json.dumps(data)
# Retrieve it
stored = state.get("my_data")
if stored:
data = json.loads(stored)
Example: Monitor a webpage for changes
import requests
import hashlib
import os
from state import state
URL = os.environ.get("URL", "https://example.com")
# Fetch the page
response = requests.get(URL)
content = response.content
current_hash = hashlib.md5(content).hexdigest()
print(f"Page hash: {current_hash}")
print(f"URL: {URL}")
# Compare with previous hash
last_hash = state.get("last_hash")
if last_hash and last_hash != current_hash:
print("PAGE CHANGED!")
elif last_hash:
print("No change detected")
else:
print("First run - storing initial hash")
state["last_hash"] = current_hash
Example: Track consecutive failures
import requests
import os
from state import state
API_URL = os.environ.get("API_URL", "https://api.example.com/health")
FAILURE_THRESHOLD = 3
try:
response = requests.get(API_URL, timeout=10)
status = response.status_code
print(f"Status: {status}")
if status == 200:
print("API is healthy!")
# Reset failure counter on success
if state.get("consecutive_failures", 0) > 0:
print("Recovered from previous failures")
state["consecutive_failures"] = 0
else:
print(f"Warning: Unexpected status code {status}")
except Exception as e:
# Track consecutive failures
failures = state.get("consecutive_failures", 0) + 1
state["consecutive_failures"] = failures
print(f"ERROR: API check failed - {e}")
print(f"Consecutive failures: {failures}")
if failures >= FAILURE_THRESHOLD:
print(f"ALERT: {failures} consecutive failures!")
raise
Example: Track price changes
import requests
import re
import os
from state import state
PRODUCT_URL = os.environ.get("PRODUCT_URL", "https://example.com/product")
# Fetch the product page
response = requests.get(
PRODUCT_URL,
headers={"User-Agent": "Mozilla/5.0"}
)
html = response.text
# Extract price (customize this regex for your target site)
price_pattern = r'\$([\d,]+\.\d{2})'
matches = re.findall(price_pattern, html)
if matches:
price = matches[0]
print(f"Current price: ${price}")
# Compare with previous price
last_price = state.get("last_price")
if last_price and last_price != price:
print(f"PRICE CHANGED: ${last_price} -> ${price}")
elif last_price:
print("Price unchanged")
else:
print("First run - storing initial price")
state["last_price"] = price
else:
print("Could not find price on page")
Limits
Total state size is limited to 64 KB per script. If your state exceeds this limit, the run will fail with an error.
Persistence
State is durable and persists across runs. It's stored separately from your script, so updating your script code doesn't affect stored state.
To clear state, either:
- Set keys to empty strings in your script
- Use the Clear state button in the dashboard
State is per-script
Each script has its own isolated state. Scripts cannot read or write each other's state.