Guides
Sites and robots.txt
Put the entry from the where.sites column in where.sites. A site marked "needs a terms review before use" is refused with site_not_reviewed until someone at Snag has read its terms; see robots.txt. A site that needs a key on our server says so with site_unavailable when the key isn't set, and so does a site that walls this server off ("not available").
For dates, attributes.from and attributes.to are YYYY-MM-DD, inclusive. Readers that take a time zone read attributes.time_zone (an IANA name like America/New_York). These and the other request settings below (party size, ids, selector) tell the reader what to fetch; they never filter results the way size or color do.
Stores
| Site | where.sites | match | Gives |
|---|---|---|---|
| Any online store | nalgene.com, keychron.com, tandemceramics.com/shop | url, line, category | Finds the platform on the first check (Shopify, WooCommerce, Squarespace, BigCommerce or Magento) and reads it with that platform's reader below; any other store's product page is read as schema.org. Checked at most hourly, like Shopify, since the platform isn't known until then |
| Any Shopify store | a /products/ link, as a url match | url, line, category | price, stock, quantity, every option |
| Any WooCommerce store | nalgene.com/product-category/bottles | url, line, category | price (exact), stock, low-stock count, every variation option |
| Any Squarespace store | tandemceramics.com/shop, <name>.squarespace.com | url, line, category | price (exact), stock and count per variant, every option. A listing reads 8 products in full a run |
| Any BigCommerce store | store.com/shop-all (a category page), <name>.mybigcommerce.com | url, line, category | url: price and stock per option combination (up to 24); listings: price and Add to Cart per product. A line watch needs a category page, since BigCommerce's search is disallowed by robots.txt |
| Any Magento / Adobe Commerce store | www.vitamix.com, or a store view like bulk.com/uk | url, line, category | price (exact) and stock per configurable variant, every option, sale and regular price |
| Any page with schema.org product data | sweetwater.com | url | price, stock |
| Nike | nike.com | url, sku | price, stock per size, low stock, release date |
| Amazon | amazon.com | url, sku, exact | price, stock |
| Running Warehouse, Zappos, Brooks, Saucony, On, adidas, New Balance | the store's host | url, some sku or exact | price, stock per size |
If a store isn't listed, preview a product URL from it. Most stores run on one of these platforms or publish schema.org data, and those work without anything from us.
Marketplaces
| Site | where.sites | match | Gives |
|---|---|---|---|
| eBay | ebay.com (or ebay.co.uk, ebay.de, ebay.ca, ebay.com.au), a search link ebay.com/sch/i.html?_nkw=leica+m6&_udhi=1500&LH_Auction=1, or ebay.com/itm/<id> | url, line, category, listing | Listings, newest first (auctions ending soonest first): exact price (the current bid for auctions), seller, listed date, condition, ends_at and bids for auctions, shipping, seller feedback. The search link's price range, format, condition and category are passed to eBay. Needs EBAY_CLIENT_ID and EBAY_CLIENT_SECRET |
| Discogs | discogs.com/release/249504 or discogs.com/seller/<name> | url, listing, line, category | A release: the lowest asking price (USD, exact) and how many copies are for sale. A seller: their newest listings. Seller inventories need a terms review before use (robots.txt disallows /users/). DISCOGS_TOKEN is optional and raises the rate limit |
| Reverb | reverb.com, a search link reverb.com/marketplace?query=boss+ce-2&price_max=200&condition=used, or reverb.com/item/<id> | url, line, category, listing | Music gear: make, model, exact price, shop, listed date, condition, finish, year. Searches come back in Reverb's order, not newest first (robots.txt disallows sort), so use a narrow search |
| Etsy | etsy.com, a search link etsy.com/search?q=mechanical+keyboard&min=50&max=200, or etsy.com/listing/<id> | url, line, category, listing | Active listings, newest first: exact price, quantity, listed date, shop, favorites. Needs ETSY_API_KEY |
reddit.com/r/Pen_Swap, or reddit.com/r/pens+fountainpens | url, line, category | the newest posts: title, link, author, posted time, price from the title or text, and whether it's sold. New posts show up within about 15 minutes; a new subreddit's first check takes about 5 |
Apartments
| Site | where.sites | match | Gives |
|---|---|---|---|
| Apartment listings (AppFolio) | sdppm.appfolio.com, cbpm.appfolio.com/listings, or a manager's own page with AppFolio's embed (sdppm.com/available.html) | url, listing | One listing per unit for rent: exact monthly rent, beds, baths and sqft as numbers, the move-in day as date (a unit listed as available now gets the check's day, Pacific time), address. attributes.property_group limits it to one AppFolio property group; a group AppFolio doesn't know reads as empty, so check the name. A unit with no rent gets price_missing |
| Apartment unit maps (SightMap) | A community page with a sightmap.com unit map (oakrow.com/floorplans), or sightmap.com/embed/<id> | url, listing | One listing per available unit: exact rent (total_monthly too when fees are added), available_date, beds, baths, sqft, unit number, floor plan, building, floor, lease term, and the leasing system behind it (yardi_rentcafe, realpage_v2, ...) |
| RentCafe | rentcafe.com, securecafe.com | url, listing | Not supported: Cloudflare blocks us, robots.txt disallows the unit pages, and the API needs a key from Yardi. Watch the community's own floor plans page if it has a SightMap unit map. Refused with site_unavailable |
| Entrata | <property>.prospectportal.com | url, listing | Not supported: Cloudflare blocks every request, robots.txt included. Refused with site_unavailable |
A page whose path is about units to rent (/floorplans, /available.html, /apartments/...) goes to the apartment reader. If it shows neither AppFolio nor SightMap, it's read by a learned recipe instead.
Booking and appointments
Booking readers give one slot per open time. Use { "field": "availability", "op": "=", "value": "open_slot" }.
| Site | where.sites | match | Gives |
|---|---|---|---|
| Cal.com | cal.com/peer/15, cal.com/team/cal/intro, acme.cal.com/jane/30min | listing, url | One slot per open time from from to to (default 14 days) in time_zone (default UTC): start with offset, duration, host, price, seats left on seated events. attributes.duration picks a length on events with several |
| Calendly | calendly.com/<user>/<event> | listing, url | One slot per open start time (14 days by default, up to 93), seats left for group events, length, location, host. attributes.timezone reads the days in another zone. Needs a terms review before use |
| Acuity Scheduling | app.acuityscheduling.com/schedule.php?owner=26704703, <name>.as.me | url, line, category | One item per appointment type: name, exact price, duration_minutes, category, service_id. Open times need a terms review before use (robots.txt disallows /api/*) |
| Square Appointments | book.squareup.com/appointments/<id>/location/<id>/services | url, line, category; listing after a terms review | One item per service: fixed price, duration_minutes, category, staff, place. Open times (listing, with service or service_id, staff or staff_id, from, to, up to 62 days) are built but off: app.squareup.com's robots.txt disallows the availability API, so they need a terms review before use, and then fetch.accept_site_terms and the browser |
| Jane App clinics | versamc.janeapp.com, versamc.janeapp.com/locations/versa-movement-collective/book, .../book#/staff_member/2/treatment/1, <clinic>.janeapp.co.uk | listing, url | One slot per open appointment time for one visit type at one location, from to to (about 14 days by default, at most 28): the start with the clinic's offset, length, practitioner, visit type, location, and the price when the clinic shows it. Set the visit type with treatment_id or treatment, the practitioner with staff_member_id or practitioner (or leave it out for every practitioner), and location when there are several. Without a visit type the check fails and lists the clinic's visit types |
| SimplePractice (therapy, counseling, small clinics) | example-practice.clientsecure.me | listing, line, category | One slot per open appointment time for the next 7 days (at most 14): exact start and end with offset, clinician, service, length, office or video, and the listed rate. Narrow with clinician, service, video, time_zone; without time_zone the days are picked in New York time (time_zone_default). Only the public booking times are read, never client data. Call-to-book services are skipped |
| Vetstoria vet booking | us.vetstoria.com/booking/<clinic> | listing, line | Needs a terms review before use: Vetstoria's terms forbid bots, and its open times only come from starting a booking at the clinic |
| NexHealth | app.nexhealth.com/appts/<practice> | listing, url | Once reviewed: one slot per open time per provider at one location (location_id, optional provider_id, slot_length). Needs a terms review before use |
| Zocdoc | www.zocdoc.com/doctor/<name>-<id> | listing, url | Not supported: Zocdoc puts a bot check in front of every page. Refused with site_not_reviewed |
| Epic MyChart open scheduling | <health system>/mychart/SignupAndSchedule/EmbeddedSchedule?id=..&dept=..&vt=.. | listing, url | Not supported yet: the pages need a browser session, and Epic's and the health system's terms haven't been read. Refused with site_not_reviewed |
| Fresha | fresha.com/a/perfect-color-salon-waukegan-1206-golf-road-xkd1xi4g | url, line, category | One item per service variant: exact price (a "from" price goes in price_from with price_type: starts_at), duration_minutes, category, restriction ("Female only"), place. attributes.service picks one service. Group appointments the page doesn't list are left out, and the check flags partial_data. No open times: Fresha shows them only inside a booking cart on the salon's account (and may ask for a reCAPTCHA), so they're off until someone decides carts are acceptable |
| Booksy | booksy.com/en-us/388730_barber-shop-nyc_barber-shop_30067_new-york-city | url, line, category | One item per service variant: exact price ("$65.00+" goes in price_from), duration_minutes, category, staff. attributes.staff (a name) or staff_id keeps what that person does. When only the page's schema.org offers can be read (partial_data), the number goes in price_from with price_type: unknown and price is empty. No open times: Booksy's slot API is disallowed by robots.txt |
| Vagaro | vagaro.com/<business> | url, line, category | Not supported yet: Vagaro's robots.txt disallows every page for our crawler. Needs a terms review before use |
| Boulevard | joinblvd.com/b/<business>/widget, blvd.app/@<business> | url, line, category, listing | Not supported yet: the widget creates a cart on the salon's account as soon as it opens, before it shows services or times. Needs a review before use |
| Trusted Traveler interviews | ttp.cbp.dhs.gov/5140 (a location id) | listing | Global Entry, NEXUS and SENTRI interview slots with open spots, in the center's local time |
| Recreation.gov permits | recreation.gov/permits/233262 | listing, url | One slot per entry point per day: permits left, walk-up flag. attributes.division picks one trailhead. Needs a terms review before use |
| Recreation.gov campsites | recreation.gov | listing | Open campsite nights. Needs a terms review before use |
Restaurants
Ask for attributes.party_size (default 2) and either date or from/to in the restaurant's local time, at most 14 days per check. time_from and time_to (HH:MM) narrow the hours. Slots carry party_size, seating, local_date, local_time and time_zone.
| Site | where.sites | match | Gives |
|---|---|---|---|
| Resy | resy.com/cities/ny/venues/lilia | listing, url | Every open time for your party, with seating (Dining Room, Bar, Patio), length, deposit and cancellation fee. Needs RESY_API_KEY |
| OpenTable | opentable.com/r/carbone-new-york | listing, url | Times around the time you ask for, open or taken, with seating and table type. Needs OPENTABLE_AVAILABILITY_HASH. OpenTable's bot protection blocks us at the moment |
| Tock | exploretock.com/alinea | listing, url | Each time and experience for your party, with tickets left and the prepaid price. Cloudflare blocks us at the moment |
Tickets and events
| Site | where.sites | match | Gives |
|---|---|---|---|
| Eventbrite | eventbrite.com/e/snakehips-twofaced-tickets-1993478754618 | url, listing | Lowest and highest price, on sale, sold out or not yet, sales start (opens_at) and end, start time, venue. With EVENTBRITE_TOKEN set, each ticket class too |
| Luma | luma.com/u9l1w54q (an event), luma.com/genai-sf (a calendar), luma.com/sf (a city) | url, listing, line | Events: exact price, open, low, sold out or waitlist, spots left, start time, place. On an event page, each ticket type |
| Ticketmaster | ticketmaster.com | url, line, category, listing (with attributes.venue_id or attraction_id) | Face-value price range, on-sale state, on-sale time (opens_at), start time, venue. Needs TICKETMASTER_API_KEY |
| SeatGeek | seatgeek.com | url, line, category, listing (with attributes.performer or venue_id) | Lowest resale price, listing count, average and median price. Needs a terms review before use (its API's robots.txt disallows everything) and SEATGEEK_CLIENT_ID |
| DICE | dice.fm/event/6a0b2ac3c6b6f90001b98470 (an event), dice.fm/browse/london (a city), dice.fm/venue/earth-76a7 (a venue) | url, listing, line | Events: exact price (or the lowest when there are several ticket types, marked price_from), on sale, sold out or announced, waiting list, sale and presale start (opens_at), start time, venue, promoter. Ticket types aren't read (ticket_types_not_read) |
| Meetup | meetup.com/torontojs (a group's upcoming events), meetup.com/torontojs/events/317276003 (an event) | url, listing, line | Events: the fee and how it's paid, spots left against the limit, going and waitlist counts, full or RSVPs closed, RSVP opening (opens_at, on event pages), start time, venue, group |
| Tito | ti.to/clearleft/ux-london-2027 (an event), ti.to/clearleft (an organizer's events) | url, listing, line | On an event: each ticket type with its exact price, available, low, sold out, waiting list or not yet on sale, tickets left when shown, sale start (opens_at) and end, tax note, and the event date. A time with a named zone is exact; a time with no zone keeps only the date, with the clock time in local_start. An organizer: its upcoming events, without prices. In conditions, give prices as a bare number for GBP and EUR events |
| Partiful | partiful.com/e/AWx1DaE9DfUoBmqFTaVU | url | Public events only: open, low, full or closed, spots left, capacity, waitlist, RSVP deadline, start time, place, guest counts (no names). Partiful's own status decides; an event cancelled only in its description still reads as open |
| Sessionize | sessionize.com/ndc-oslo-2027 (a call for speakers), sessionize.com/api/v2/jl4ktls0 (a published schedule) | url, listing, line | A call: open, upcoming or closed, exact closing time, opening time (opens_at), event days, venue, travel and fee offers. A schedule: one listing per session with start, end, room, speakers, track |
| start.gg | start.gg/tournament/genesis-x2, or listing with attributes.videogame_id | url, listing, line | Tournament registration open or closed, closing time, attendees, start time, venue; each event's entrants and game. Needs STARTGG_TOKEN |
| AXS | axs.com | url, listing | Not available: AXS answers this server with a bot check, and its API is for partners only |
| See Tickets | seetickets.com, seetickets.us | url, listing | Not available: both answer this server with a bot check (seetickets.us is now eventim.us) |
Classes, courts and tee times
| Site | where.sites | match | Gives |
|---|---|---|---|
| ActiveNet (city recreation) | activecommunities.com/denver | url, line, category, listing | One slot per program: spots left, class size, fee, first session time, place, and opens_at while registration hasn't opened. Full, closed and cancelled are out of stock |
| CivicRec (Rec1) city recreation | secure.rec1.com/CA/temecula-ca | listing, line, category | One slot per program session: exact start with the agency's offset, fee, days, ages, place, and opens_at while registration hasn't opened. Full, closed and cancelled are out of stock. Rec1 doesn't publish spots left, so quantity is empty. Pick tabs with tab ("Swim Lessons"). With kind: facilities, one slot per facility and day (from to to, 14 days by default, at most 31): available, limited or unavailable, with the rates. Facility days give the date only, not the hours (hours_not_read) |
| Amilia program registration | app.amilia.com/store/en/example-org | url, listing | One slot per activity: spots left as quantity, class size, start, schedule, ages, waitlist, and price when you set currency. With drop_in: true, also one slot per drop-in session with its own spots left. Watch by activity link (url) or activity_ids (listing). Needs AMILIA_API_TOKEN, a partner token from Amilia. Not yet checked against a live answer |
| Mindbody | mindbodyonline.com/explore/locations/dear-pilates | url, line, category, listing | One slot per class from from to to (7 days by default, 14 at most): spots open, capacity, waitlist, instructor, start time, opens_at before booking opens |
| foreUP golf tee times | foreupsoftware.com/index.php/booking/19765/2431 | listing, url | One slot per open tee time: spots left, holes, green fee, cart fee. Optional booking_class, holes and party. Needs a terms review before use |
| GolfNow tee times | golfnow.com/tee-times/facility/1225-audubon-park-golf-club | listing, url | One slot per open tee time from from to to (3 days by default, 7 at most): per-player rate, holes, rate name, Hot Deal, transaction fee, and the largest group it takes as quantity. Optional holes (9 or 18), party (1 to 4) and time_zone. Without time_zone, times use the course's offset on the day of the check, so a window that crosses a clock change is an hour off on the far side |
| Chronogolf tee times | chronogolf.com/club/miami-beach-golf-club | listing, url | One slot per open tee time at every course of the club (3 days by default, 7 at most): spots left, holes, starting hole, public green fee, deals; a held time is out_of_stock. Optional holes and party. Chronogolf's firewall blocks this server's tee-time requests for now, so checks report blocked |
| Mariana Tek class schedules | barrysbootcamp.marianatek.com?location=10462 | url, line, category, listing | One slot per class (7 days by default, 14 at most): spots left (when the studio shows them), class size, waitlist, instructors, room, opens_at before booking opens. Needs a terms review before use |
| Playtomic courts | playtomic.com/clubs/02-padel-sport-academy | listing, url | One slot per free court time (3 days by default, 7 at most): court, length, price, indoor or outdoor. Optional sport (PADEL or TENNIS), duration, court, indoor. Needs a terms review before use |
| CourtReserve court bookings | app.courtreserve.com/Online/Reservations/Bookings/12345 | listing, url | Needs a terms review before use: CourtReserve's robots.txt disallows everything, and most court grids need a member login |
| Zen Planner class schedules | crossfitexample.sites.zenplanner.com/calendar.cfm | listing, url | Not read yet: robots.txt disallows the calendar. Needs a terms review, then a reader |
| ClassPass studios | classpass.com/studios/<studio> | listing, url | Not available: ClassPass challenges every request from this server. Watch the studio's own booking page instead (Mindbody, Mariana Tek) |
Jobs
Each open job is a listing; a closed one drops out. Use match: line with words from the title.
| Site | where.sites | match | Gives |
|---|---|---|---|
| Greenhouse | boards.greenhouse.io/discord | listing, line, category | title, link, date posted, location, department, team, remote, req id |
| Lever | jobs.lever.co/spotify | listing, line, category | title, link, date, location, department, team, employment type, remote, salary when published |
| Ashby | jobs.ashbyhq.com/notion | listing, line, category | title, link, date, location, department, team, employment type, remote, salary when published |
| Workday | nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite | listing, line, category | title, link, posting date (from "Posted N days ago"), location, remote, req id. The first 100 jobs a run |
| SmartRecruiters | careers.smartrecruiters.com/BoschGroup | listing, line, category | title, link, date, location, department, employment type, remote. Needs a terms review before use |
Software, games and status pages
| Site | where.sites | match | Gives |
|---|---|---|---|
| GitHub releases | github.com/nodejs/node | url, line | version (major), status, date |
| GitHub commits | github.com/nodejs/node/commits/main, github.com/nodejs/node/blob/main/doc/api/fs.md, github.com/nodejs/node/tree/main/lib | listing, line, url | New commits on a branch, or only those that touch a file or folder: sha, title, date, author login, message, verified, parents. A branch with a slash goes in attributes.branch. A path no commit has touched yet reads as none, so check the path |
| GitHub repository stats | github.com/nodejs/node/stargazers | url, listing | One record whose stars, forks, watchers, open_issues and size_kb are numbers, so stars >= 10000 or compare_to works. Also default branch, language, license, archived, pushed_at |
| GitHub issues and pull requests | github.com/nodejs/node/issues, github.com/nodejs/node/pulls | listing, line, url | The newest 100 open (or closed, with attributes.state) issues or PRs, with words matched in the title or labels and attributes.label sent to GitHub: number, author, labels, comments, reactions, thumbs_up, draft, merged_at |
| GitHub security advisories | github.com/advisories/npm/lodash, github.com/advisories/pip/jinja2 | listing, line, url | Reviewed advisories for one package, newest first: GHSA and CVE ids, severity, cvss_score, the vulnerable range, the patched version, withdrawn. attributes.affects_version and severity are sent to GitHub. A misspelled package reads the same as one with no advisories |
| OSV.dev | osv.dev/PyPI/jinja2, osv.dev/Go/github.com/gin-gonic/gin, osv.dev/vulnerability/GHSA-35jh-r3h4-6jhm | listing, line, url | Every known vulnerability for a package in any OSV ecosystem, or one by id: aliases (CVE, GHSA), fixed versions, severity, a cvss_score worked out from CVSS 3.x, modified. attributes.affects_version keeps the ones that affect that version. Only the first page is read (partial_results says so). No key |
| NVD (National Vulnerability Database) | nvd.nist.gov plus words, nvd.nist.gov plus attributes.cpe, nvd.nist.gov/vuln/detail/CVE-2021-44228 | listing, line, url | CVEs published in the last 119 days that match the words or the CPE (the newest 200), or one CVE: cvss_score, cvss_version, severity, status, CWEs and kev (on CISA's exploited list). Checked every 2 hours at most. NVD_API_KEY is optional |
| npm | npmjs.com/package/react, npmjs.com/package/@types/node | url, line | Versions: major as version, semver, prereleases (announced), dist-tags, deprecated, publish date |
| crates.io | crates.io/crates/serde | url, line | The 30 newest versions: semver, yanked, downloads, publish date |
| Docker Hub | hub.docker.com/_/node, hub.docker.com/r/grafana/grafana | url, line | The 100 most recently pushed tags, or the ones in attributes.tag: digest (watch it with changed), version, size, platforms, push time |
| PyPI | pypi.org/project/requests | url, line | Versions, prereleases, yanked, upload date. Needs a terms review before use (robots.txt disallows the JSON API) |
| Steam | store.steampowered.com/app/1245620 | url, sku | Exact price in the currency of location.country, price before discount, discount_percent, coming soon, release date |
| Statuspage (and incident.io) | statuspage:www.cloudflarestatus.com, statuspage:status.clerk.com | listing, url, line, category | One record per component (status: operational, degraded_performance, partial_outage, major_outage, under_maintenance), the page's overall state, open incidents and scheduled maintenances. Many pages hosted on Statuspage (*.statuspage.io, githubstatus.com) disallow /api/ in robots.txt and fail with robots_disallowed |
| Instatus | instatus:status.zed.dev, railway.instatus.com | listing, url, line, category | The same records as Statuspage, in the same words |
Feeds and posts
| Site | where.sites | match | Gives |
|---|---|---|---|
| Any RSS, Atom or JSON feed | blog.rust-lang.org/feed.xml, example.substack.com, or feed:blog.rust-lang.org for a page that links its feed | url, listing, line, category | The newest 100 items: title, link, published time, author, categories, a plain-text summary, and for podcasts the audio file and length |
| Hacker News | news.ycombinator.com, news.ycombinator.com/show, /ask, /jobs, /newest, /user?id=pg | listing, line, category | Stories: title, discussion link, posted time, author, points, comments, the link and its domain |
| Bluesky | bsky.app/profile/bsky.app, or bsky.app with words in target.query | listing, line, category | The newest 50 posts: text, link, time, author, likes, reposts, replies |
| Wikipedia page edits | en.wikipedia.org/wiki/Earth (any language) | url, listing | The newest 20 revisions: editor, time, summary, size and bytes changed |
| YouTube | youtube.com/@GoogleDevelopers, youtube.com/playlist?list=... | url, listing, line, category | The latest 15 videos. Needs a terms review before use (robots.txt disallows the feed) |
| Stack Exchange questions | The question link, https://stackoverflow.com/questions/<id>/... (any Stack Exchange site) | url, listing | A post: score, answer_count, view_count, accepted, accepted_answer_id, closed, closed_reason, tags. 300 requests a day per server without STACKEXCHANGE_KEY |
Books and streams
| Site | where.sites | match | Gives |
|---|---|---|---|
| Open Library | openlibrary.org/authors/OL7234434A (an author), openlibrary.org/works/OL82563W (a book's editions), openlibrary.org/books/OL62447619M or openlibrary.org/isbn/9781551927282 (one edition) | url, listing, line | One release per work or edition: title, publish date (an exact day when Open Library has one, else publish_year), publishers, format, pages, languages, ISBN as GTIN, scan id. Use { "field": "items", "op": "added" } for new works or editions. Ids only, no name search (robots.txt disallows search). The first 100 works or 50 editions are read |
| Open Library loans | archive.org/loans, with an archive.org/details/<id> link as the url query | url | Whether a scan can be borrowed now, copies free, waitlist size. Needs a terms review before use |
| Twitch | twitch.tv/somechannel, or category with a game name | url, category | One profile per channel: live or offline (in_stock while live, so back_in_stock means it went live), stream title, game, viewers, start time. Needs a terms review before use (its API's robots.txt disallows everything) and TWITCH_CLIENT_ID with TWITCH_CLIENT_SECRET |
Markets
Quotes are exact: a price of $0.000002808 is compared as that, not rounded to a cent.
| Site | where.sites | match | Gives |
|---|---|---|---|
| DexScreener | dexscreener.com, with a pair or token link https://dexscreener.com/solana/<address> as a url match, or a symbol for line | url, sku (solana:<address>), line | A quote: USD price, price_change_5m/1h/6h/24h, volumes, liquidity_usd, fdv, market_cap. A symbol search can rank a lookalike token first, so prefer the address |
| OpenSea | opensea.io/collection/pudgypenguins | url, sku (the slug), line | The collection floor as a quote in its currency, volume, sales, owners. Needs OPENSEA_API_KEY |
| Magic Eden (Solana NFTs) | magiceden.io/marketplace/okay_bears | url, listing; sku only for a symbol without underscores | The collection floor as a quote in SOL, exact, with listed_count, avg_price_24h and volume_7d in SOL as numbers, plus the 20 cheapest listings as listing items (exact SOL price, rarity ranks, traits as trait_<type>). listings: false reads the floor only. An unknown symbol reads as an empty collection (nothing_listed), so check the symbol on magiceden.io first. No key. Needs a terms review before use (Magic Eden's API terms limit passing its data on) |
| Etherscan (wallets and gas) | etherscan.io/address/0x..., polygonscan.com/address/0x..., arbiscan.io/address/0x..., etherscan.io/gastracker | listing, url | For an address: a record per recent transaction and ERC-20 transfer (50 of each, newest first) with direction (in, out, self), value in the coin or token as a number (value_wei exact), fee, block, method, failed, token symbol, contract and reputation. direction, token and include narrow it. For a gas tracker: a quote in gwei with safe_gwei, propose_gwei, fast_gwei. Free-tier chains only (Ethereum, Polygon, Arbitrum, Linea and others); Base, BNB, Optimism and Avalanche need a paid Etherscan plan (paid_plan_required). A wallet can belong to a private person: you pick the address and it's your responsibility. Needs ETHERSCAN_API_KEY and a terms review before use (the free plan is for personal and research use) |
| CoinGecko | coingecko.com/en/coins/bitcoin | url, sku (the coin id), line | Coin price in attributes.vs_currency (usd by default), market cap, 24h volume and change. Needs a terms review before use (robots.txt disallows /api/v3). COINGECKO_DEMO_API_KEY is optional |
| Kalshi | kalshi.com (a market ticker as the sku query), kalshi.com/markets/kxfed/fed-meeting/kxfed-27apr (an event), kalshi.com/markets/kxfed (a series) | sku, url, listing | One quote per market. price is the last Yes trade in dollars (0.56 = 56%), or empty if the market has never traded. yes_bid, yes_ask, no_bid, no_ask, volume, volume_24h, open_interest and strikes are numbers. No key |
| Polymarket | polymarket.com/event/<event-slug>, polymarket.com/event/<event>/<market>, or polymarket.com with a market slug (sku) or words (line) | url, sku, line | One quote per outcome (just Yes for a Yes/No market), the exact price in dollars. best_bid, best_ask, spread, last_trade_price, volume, volume_24h, liquidity, price_change_1d and price_change_1w are numbers. No key. Checked every 5 minutes at most, because Polymarket caches answers for 5 minutes |
| Stock quotes (Finnhub) | finnhub.io with a symbol as the sku query (AAPL) | sku | One quote per U.S. symbol: the price in USD, plus change, change_percent, open, high, low, previous_close and updated_at. Needs FINNHUB_API_KEY, and a terms review before use (free market-data plans are for the key holder's own use) |
| Crypto exchange listings (Coinbase, Kraken) | coinbase.com/listings, kraken.com/listings, with currencies as the query ("SOL", "usd") | listing | A record per trading pair: pair, base, quote, status (online, auction, post_only, limit_only, cancel_only, disabled, delisted), trading. A new listing is items added. No prices |
Rates and economic data
| Site | where.sites | match | Gives |
|---|---|---|---|
| U.S. Treasury Fiscal Data | fiscaldata.treasury.gov/v2/accounting/od/debt_to_penny, or any Fiscal Data API endpoint, with the API's ?filter= if you want one | url, line | One record per row of the newest release (date is its record_date). Every numeric column is a number under its API name (tot_pub_debt_out_amt, avg_interest_rate_amt, exchange_rate), and text columns can be pinned with target attributes. A release longer than one page is read whole, up to 10,000 rows. No key |
| FRED | fred.stlouisfed.org/series/UNRATE, or fred.stlouisfed.org with the series id as the sku query | url, sku | One record per series: value, previous_value, change, change_percent, period, units and frequency, with date the newest observation. Needs FRED_API_KEY |
| BLS | data.bls.gov/timeseries/CUUR0000SA0, or bls.gov with the series id as the sku query | url, sku | One record per series: value, previous_value, change, change_percent, period_name, with date the first day of the newest period. BLS_API_KEY is optional. Needs a terms review before use (api.bls.gov's robots.txt disallows everything) |
| European Central Bank | ecb.europa.eu with a currency code (line: USD), data.ecb.europa.eu/data/datasets/EXR/EXR.D.USD.EUR.SP00.A, or FLOW.KEY as the sku query | line, url, sku | A euro reference rate is a quote: the price of one euro in that currency, exact. Any other series (deposit rate, €STR) is a record. Both carry value, previous_value, change, change_percent and unit. A + in the key gives several series at once. No key |
| U.S. economic release calendars (BLS, BEA) | bls.gov/schedule, bea.gov/schedule, with words as the query ("consumer price index", "GDP") | listing | A release per scheduled release from the past week on: date with its Eastern-time offset, release_date, release_status (announced, then available once the time passes), agency, release, period. A reschedule keeps the key, so date changed catches it. Dates only, not the numbers |
Government
| Site | where.sites | match | Gives |
|---|---|---|---|
| SEC EDGAR filings | sec.gov/AAPL, sec.gov/cik/320193 | listing, url | The newest 100 filings: form, filing date, archive link, 8-K items |
| Companies House (UK companies) | find-and-update.company-information.service.gov.uk/company/00445790 (add /filing-history or /officers to read only that part) | listing, url | A record for the company (status, accounts and confirmation statement due dates, accounts_overdue, has_insolvency_history, SIC codes, filings_total, active_officers), one per filing (form like CS01 or AA, category, readable description, processed date, PDF link) and one per officer appointment (name, role, appointed_on, resigned_on, active). form: ["AA"] or category: ["accounts"] narrows filings. Officers' birth dates and addresses are never read. A watch on officers names private people; that choice is yours. Needs COMPANIES_HOUSE_API_KEY (free). Not yet checked against a live answer |
| NHTSA vehicle recalls | nhtsa.gov/recalls/honda/accord/2018 | listing, line, category | Each recall campaign: component, summary, consequence, remedy, park-it warnings |
| CPSC product recalls | cpsc.gov/recalls, with words in target.query | listing, line, category, url | Recalls from the last 60 days with every word: hazard, remedy, units, where sold |
| openFDA drug shortages | open.fda.gov/drug/shortages, with the drug in target.query | listing, line, category, sku | Shortage entries per package, with availability, status and reason. OPENFDA_API_KEY is optional |
| openFDA recalls | open.fda.gov/drug/enforcement, /food/enforcement, /device/enforcement | listing, line, category | Enforcement reports: class, status, reason, firm, lots |
| Federal Register | federalregister.gov, federalregister.gov/agencies/<slug> | listing, line, category | Rules, proposed rules and notices: type, comment deadline, effective date |
| Grants.gov | grants.gov, grants.gov/agencies/HHS-NIH11 | listing, line, category | Open and forecast funding opportunities with open and close dates |
| City and county meetings (Legistar) | legistar:seattle, oakland.legistar.com | listing, line, category | listing: upcoming meetings (start time with offset, agenda and minutes status, cancelled, agenda PDF). Words: matching agenda items from the next 12 agendas (matter file, type, status, action). Meetings and items are records. attributes.time_zone is needed for cities without a known zone; without it you get the day only, plus time_zone_unknown. An unknown client name answers 500 and reads as unreachable |
| US wildfires (NIFC) | wildfire:CA, wildfire:2026-CALPF-002271, wildfire with a location | listing, line, category | Current incidents: name, acres, percent_contained, personnel, county, cause, discovered, contained and out dates, point of origin. Prescribed burns with attributes.include_rx |
| InciWeb | inciweb | listing, line, category | Needs a terms review before use: inciweb.wildfire.gov's robots.txt disallows everything, so nothing is fetched. Use wildfire: |
| Road work and closures (WZDx) | roadwork:WA, roadwork:MN, wzdx:https://<feed> | listing, line, category | Work zones and detours: road, direction, vehicle_impact, start and end, active, mileposts. attributes.closed_only, attributes.road, and a location radius with distance_miles. closed_only on a feed that marks every impact unknown (WSDOT) adds impact_unknown; a feed that hasn't updated in a long time adds feed_stale |
| AirNow air quality | airnow:94110, or airnow with a location | listing | Current AQI per pollutant plus an overall record, and forecasts with category and action_day. Needs AIRNOW_API_KEY (free). Not yet checked against a live answer |
| USGS earthquakes | earthquake.usgs.gov/m4.5, earthquake.usgs.gov/near/34.05,-118.24/200km | listing, line, category | Events in the last 7 days: magnitude, depth, alert level, tsunami flag |
| CourtListener | courtlistener.com/opinions/scotus, courtlistener.com/dockets/cand | listing, line, category | New opinions or dockets. Needs COURTLISTENER_TOKEN |
| NWS weather alerts | weather.gov/alerts/area/KS, weather.gov/alerts/zone/KSZ009 | listing, line, category | Active alerts: event, severity, urgency, onset and expiry. Needs a terms review before use |
| USAspending.gov | usaspending.gov, https://www.usaspending.gov/award/CONT_AWD_.../ | listing, line, category, url | Federal contract, IDV or grant awards from the last 90 days (days, up to 365), or one award: the exact amount as the price, recipient, agency, signed date, place of performance, NAICS and PSC. award_type, agency, sub_agency, recipient, state, naics, psc, min_amount and max_amount narrow the search. Department of Defense contracts show up about 90 days late, so use days: 180 or more for DoD. An IDV's amount is often $0, since the money sits on its orders |
| SAM.gov | sam.gov, https://sam.gov/opp/<notice id>/view | listing, line, category, url | Contract opportunities posted in the last 30 days: type, agency, NAICS, set-aside, response deadline with its offset, award amount and awardee. Needs SAM_API_KEY; checked every 3 hours at most, since a personal key gets 10 requests a day |
| USAJOBS | usajobs.gov, https://www.usajobs.gov/search/results/?k=nurse&l=Denver | listing, line, category, url | Open federal job announcements: agency, place, posted and closing dates, salary range and grades. Needs USAJOBS_API_KEY and USAJOBS_USER_AGENT_EMAIL, and a terms review before use |
| NOAA space weather (Kp index) | swpc.noaa.gov/kp | listing | A record per 3-hour step from the last 24 hours on: kp (0 to 9; 5 and up is a storm), status (observed, estimated, predicted), noaa_scale (G1 to G5) |
| Hospital price files | uchealth.org/cms-hpt.txt (the hospital's site plus /cms-hpt.txt), or that link as a url match | listing, url | A record per location from the hospital's CMS index: mrf_url (the price file), source_page_url, file_type, ein. New locations and moved files, not the prices inside the files |
| US House periodic transaction reports | disclosures-clerk.house.gov/ptr, with a member's name or seat as the query ("Pelosi", "CA11") | listing | Not available yet: waiting on a review of the commercial-use limit in 5 U.S.C. §13107(c). Then a record per stock-trade report: filing date, PDF link, member, state_district, state, district. The trades themselves are inside the PDF |
Bills and regulations
| Site | where.sites | match | Gives |
|---|---|---|---|
| Congress.gov | congress.gov (the current Congress), congress.gov/bill/119th-congress/senate-bill, or a bill congress.gov/bill/119th-congress/house-bill/1 | url, listing, line | One record per bill: the latest action and its date (with the Washington-time offset when Congress.gov gives a time), status read from that action (introduced, reported, passed, to_executive, became_law, vetoed, failed, in_progress), and the bill number. A single bill adds the public law, sponsor, policy area, and action and cosponsor counts. Lists cover the 250 most recently updated bills, and search words keep titles that have every word. Watch latest_action with changed. Needs CONGRESS_API_KEY |
| Open States (state bills) | openstates.org/ca (one state), openstates.org with search words (every state), or a bill openstates.org/nc/bills/2025/HB1105 | url, listing, line | One record per state bill: latest action and date, latest passage date, status, state, session, chamber, subjects. A single bill adds the latest action's classification, the action count and the primary sponsor. session, chamber and classification narrow the list. 20 bills per check, latest action first. Needs OPENSTATES_API_KEY. Not yet checked against a live answer |
| Regulations.gov | regulations.gov with search words (documents open for comment), regulations.gov/docket/FAA-2026-10694 (everything filed in a docket), or regulations.gov/document/<id> | url, listing, line | One record per rulemaking document: type (Proposed Rule, Rule, Notice...), docket, agency, posted time, and exact comment open and close times. open_for_comment is true while comments are open, and comments_open_ended is true when there's no deadline. A single document adds the page count and PDF link. agency, document_type and open_for_comment narrow the search ([true, false] for both). Needs REGULATIONS_API_KEY |
status is our reading of the action's wording, not an official field.
Open data
| Site | where.sites | match | Gives |
|---|---|---|---|
| Socrata open data | socrata:data.cityofnewyork.us/erm2-nwe9, data.cityofchicago.org/resource/ydr8-5enu.json | listing, line, category, url | New rows of any dataset on a Socrata portal (311 requests, permits, WARN notices), newest first. Every column as an attribute, plus date and place. SOCRATA_APP_TOKEN is optional |
| ArcGIS feature layers | arcgis:https://maps2.dcgis.dc.gov/dcgis/rest/services/FEEDS/DCRA/FeatureServer/4 | listing, line, category, url | New rows of any public FeatureServer or MapServer layer (permits, zoning cases, code violations), newest first. A date the layer keeps as a day (an issue date) is the day, like 2026-11-02; other times are exact UTC. Set key_field for layers that are reloaded every night |
Attributes for both: where (a SoQL or SQL condition), q or search words (Socrata's full-text search), order, date_field, key_field, title_fields, place_field, location_field (Socrata), time_zone (Socrata: turns the portal's local times into exact ones), and limit (1 to 1000, default 200). location.zip with location.radius keeps rows within that distance.
Research
| Site | where.sites | match | Gives |
|---|---|---|---|
| ClinicalTrials.gov | clinicaltrials.gov with words in target.query, clinicaltrials.gov/search?cond=glioblastoma, clinicaltrials.gov/study/NCT00083512 | listing, url, line, category | Studies, most recently updated first: status (watch it with changed), recruiting as in_stock, phase, sponsor, enrollment, conditions, interventions, and the nearest site when location.zip and radius are set. condition, sponsor and intervention narrow the search. Needs a terms review before use (robots.txt disallows /api/) |
| arXiv category feeds | arxiv.org/list/cs.CL, rss.arxiv.org/rss/cs.CL+cs.AI | listing, line, category | Today's announcement: title, abstract, authors, categories, announce_type (new, cross, replace), arxiv_version. Words in target.query keep papers whose title or abstract has every word |
| arXiv search | arxiv.org with words (and attributes.category), or https://arxiv.org/abs/2611.07928 as a url match | listing, url, line, category | The newest 100 submissions: abstract, authors, categories, DOI, journal ref, version. Needs a terms review before use (robots.txt disallows the API) |
| PubMed | pubmed.ncbi.nlm.nih.gov with a search in target.query, pubmed.ncbi.nlm.nih.gov/?term=semaglutide | listing, url, line, category | Papers added in the last 30 days: journal, publication date, DOI, PMCID, article types. NCBI_API_KEY is optional. Needs a terms review before use (robots.txt disallows E-utilities); use Europe PMC meanwhile |
| Europe PMC | europepmc.org with a search in target.query, or https://europepmc.org/article/MED/42958891 as a url match | listing, url, line, category | Papers indexed in the last 14 days, PubMed's included (attributes.source: "MED" for PubMed only): journal, DOI, PMID, open access, cited_by |
| Semantic Scholar citations | semanticscholar.org/DOI:10.1056/NEJMoa2032183, semanticscholar.org/paper/<id> | listing, url, line, category | The 100 most recent papers citing it: venue, year, DOI, citation_count. SEMANTIC_SCHOLAR_API_KEY is optional |
Names and domains
| Site | where.sites | match | Gives |
|---|---|---|---|
| Username and package names (GitHub, Bluesky, npm) | handle:github/<name>, handle:bsky/<handle>, handle:npm/<package> | listing | One record with available (true when the platform has no such account or package), plus account_type and created_at (GitHub), did (Bluesky), version (npm). Available means the lookup was empty, not that you can register it |
| Domain registration (RDAP) | rdap:example.com | listing | available (true when the registry has no record), expires, days_to_expiry, EPP status, registrar, nameservers, dnssec, pending_delete, redemption. A 404 only means the registry has no record; reserved and premium names can 404 too. A host under a registered name (www.example.com) fails with rdap_not_registrable. TLDs with no RDAP server (.de, .io) fail with rdap_unsupported_tld, and .uk and .xyz fail with robots_disallowed because their registries' robots.txt doesn't let us in |
| TLS certificates for a domain (Cert Spotter) | certs:example.com (include_subdomains: false for the domain alone) | listing | A record per unexpired certificate for the domain and its subdomains: dns_names, issuer, not_before, not_after, wildcard, revoked. A new certificate is items added. Checked hourly at most; lookalike domains outside yours aren't searched |
Any page
Two readers cover pages nothing above reads. Both are looser than a site's own reader, so check the preview.
| Site | where.sites | match | Gives |
|---|---|---|---|
| Any page, read by a learned recipe | the page with its path: books.toscrape.com/catalogue/category/books/travel_2/index.html | url, listing, line, category | Whatever the page lists (products, slots, posts), with title, link, exact price, stock or open and taken, date. The first preview or the spawn learns how to read the page; every run after reads it without that step |
| Any page with several pages (learned recipe) | quotes.toscrape.com/page/1/ | listing, line, category, url | Every item across up to 10 pages. Paging stops at an empty page, a repeated page, a "not found" past the last page, or when the site's own "more" flag says there's no more |
| Any store page (learned recipe), with variants | shop.example.com/p/trail-runner | url, listing, line | One result per size or colour, with its own stock, price and SKU, so a size restock works on stores no platform reader knows |
| Any page with a form (learned recipe), with steps | shop.example.com/stores/pickup plus target.attributes.steps and location.zip | listing, line, url | What the page shows after typing a ZIP, picking a party size or clicking. The steps are recorded into the recipe and replayed with each watcher's values |
| Any page, watched for changes | change:https://www.mozilla.org/en-US/about/legal/terms/mozilla/ | url | One region with the text, text_hash, length, contains, and what changed last time (last_change, previous_hash, paragraph counts). With seo: true it also has the title, meta description, canonical, robots meta, noindex, h1, script hosts and seo_hash. With summarize: true it adds a short LLM summary of the change. See Conditions |
| Any PDF, watched for changes | change:https://www.irs.gov/pub/irs-pdf/fw9.pdf | url | One document with text (first 2,000 characters), text_hash, pages, pdf_title, pdf_created, pdf_modified, contains, the same last_change, and change_excerpt (the changed lines with context, which a judge condition reads, however deep in the file). Links ending in .pdf are read as PDFs; pdf: true works for other links. A link that starts answering a web page keeps its key and adds format_changed |
| A list on any page | change:https://www.cisa.gov/news-events/news with target.attributes.list: "article.c-teaser" | url | One record per item (a press release, a product, a list entry), keyed by its link or its text, with title, href, position, date from the item's <time>, and per-item contains. Use { "field": "items", "op": "added" } or "removed". A list that matches nothing on the first read fails with selector_not_found and names close selectors that do match; later an empty list is ok with list_empty |
| Any page, after form steps (browser) | change:https://www.weather.gov/ with browser: true, steps and location.zip | url | The page the steps led to, read like any change watch. See Steps and location |
| Any page, from a location (browser) | change:https://www.target.com/p/... with browser: true, cookies, locale, timezone and location.zip or lat/lng | url | The page as a visitor there sees it. Many stores go by IP or their own cookie, not the browser's position, so the site's location cookie is usually what works |
A page with no reader of its own that you name with its path ("example.com/book/haircut") is read by a learned recipe. A new page is learned only at preview and spawn, and a spawn that can't learn the page is refused with recipe_not_learned. If the layout changes and the recipe stops finding its items 3 runs in a row, it's learned again, at most once every 6 hours.
For page changes, set what to read in target.attributes: selector (a CSS selector; default the page's main text), contains (a phrase or a list), ignore (a CSS selector to drop, like a ticker), strip_noise: false to keep times with seconds, and browser: true for a page that builds its text with scripts. Also:
list: a CSS selector for repeated items. One result per item, keyed by its link, for{ "field": "items", "op": "added" }. At most 500 items; more is flaggedlist_truncated.pdf: true: read the link as a PDF. Links ending in .pdf are read as PDFs anyway.seo: true: the page's title, meta description, canonical, robots meta, h1 and script hosts, for watching your own site's tags.summarize: true: a one- or two-sentence summary of the latest change, from the server's LLM.
A selector or list that matches nothing on the first read fails with selector_not_found, naming close selectors that do match. To wait for an element to appear, watch a larger region with contains. Each change also carries change_excerpt, the changed lines with a line of context, which judged conditions read. The last version is kept in the database, so a deploy doesn't lose what changed. PDFs are fetched directly (never through the proxy), at most one request a second per host, and robots.txt is checked on every redirect.
A url match with any of these, or a link ending in .pdf, is a page-change watch even without the change: prefix. Timestamps, relative times ("5 minutes ago") and long tokens are dropped before hashing, so they don't count as a change.
Steps and location
With browser: true, target.attributes.steps runs in the page before it's read, one step per string:
| Step | Does |
|---|---|
fill <selector> => <value> | Types the value into a field |
select <selector> => <value or label> | Picks an option |
click <selector> | Clicks |
press <Key>, press <selector> => <Key> | Presses Enter, Tab, Escape, an arrow key and a few others |
wait <selector>, wait network, wait 2s | Waits for an element, for the network to go quiet, or up to 5 seconds |
End a step with ? to make it optional. {{name}} is filled from target.attributes, and {{zip}} from location.zip. At most 10 steps, 5 seconds each, and 25 seconds in all (less when the page's own load is quicker). Steps never type into password, file or card fields. A step that can't be done fails the check with step_failed and says which step. A bad step is refused at spawn with bad_steps. A captcha that guards the form is solved when the server has a captcha service set; otherwise the run is blocked.
Each account gets 200 browser runs with steps and 100 captcha solves a day (previews count), reset at 00:00 UTC. Past that, a run with steps is skipped and its check says usage_limit with the reset time; a captcha past the cap is left unsolved and the check says usage_limit instead of blocked. Steps that would send a contact, sign-up, registration, subscription, checkout or application form, or post a form after filling more than one field, are refused at spawn with steps_submit_refused (or fail the step with that reason when only the page shows it). Search forms, a single field then Enter, and GET forms are allowed.
For location, the browser gets the position (the ZIP's center when there's no lat/lng), locale ("en-US") and timezone. cookies (up to 5, name=value) are set on the page's host before it loads, like "GuestLocation=48104|42.270|-83.730|MI|US" on Target. Point steps at searches and lookups; see the limits above for the forms they won't send.
Blocks
We fetch directly, and through a residential proxy only after a store blocks us. APIs and sites that wall bots off on purpose (booking, restaurant, ticket and job sites, every API above) never go through the proxy: a block there is the site saying no.
When a page we load in a browser puts up reCAPTCHA (v2 or v3) or Cloudflare Turnstile, we solve it through a captcha-solving service and carry on, once the server has CAPTCHA_PROVIDER and CAPTCHA_API_KEY set. hCaptcha is reported as blocked. A server can turn solving off for sites nobody has reviewed (WATCHER_CAPTCHA_UNREVIEWED_HOSTS=off); a captcha there stays unsolved and the check says captcha_not_allowed. A page whose address is on a private or local network is never fetched (private_address). A site that can't be read 3 runs in a row (blocked, unreachable, or the page or subreddit is gone) sends a blocked event saying why, and its conditions stay unknown until it answers again.
robots.txt
We read each host's robots.txt once a day and don't fetch paths it disallows. A check that hits one fails with the issue robots_disallowed. A host whose robots.txt can't be read (a timeout, a server error, or a bot check in its place) is treated as disallowing everything until the next read.
Some sites disallow the paths that hold the data. Once Snag has reviewed such a site's terms, watchers on it must set:
"fetch": { "accept_site_terms": true }By setting it, you confirm you're allowed to fetch that site under its terms, and that you, not Snag, are responsible for doing so.
| Error | Means |
|---|---|
site_not_reviewed | We don't support that site yet: it needs a terms review before use |
site_terms_not_accepted | This watcher didn't set accept_site_terms |
Server keys
Self-hosting? These keys turn sites on. Each is optional; without it the site says so at spawn or reads less.
| Variable | For |
|---|---|
RESY_API_KEY | Resy |
OPENTABLE_AVAILABILITY_HASH | OpenTable |
EVENTBRITE_TOKEN | Eventbrite ticket classes |
TICKETMASTER_API_KEY | Ticketmaster |
SEATGEEK_CLIENT_ID | SeatGeek, after its review |
OPENSEA_API_KEY | OpenSea |
COINGECKO_DEMO_API_KEY | CoinGecko's higher limit |
EBAY_CLIENT_ID, EBAY_CLIENT_SECRET | eBay |
DISCOGS_TOKEN | Discogs' higher limit |
ETSY_API_KEY, ETSY_SHARED_SECRET | Etsy |
OPENFDA_API_KEY | openFDA's higher daily limit |
COURTLISTENER_TOKEN | CourtListener |
GITHUB_TOKEN | Every GitHub reader's higher limit (5,000 requests an hour instead of 60, shared), and GitHub name lookups |
NVD_API_KEY | NVD's higher limit |
SOCRATA_APP_TOKEN | Socrata's higher limit |
CONGRESS_API_KEY, REGULATIONS_API_KEY | Congress.gov and Regulations.gov (one free api.data.gov key works for both) |
OPENSTATES_API_KEY | Open States |
SAM_API_KEY | SAM.gov |
USAJOBS_API_KEY, USAJOBS_USER_AGENT_EMAIL | USAJOBS, after its review |
FINNHUB_API_KEY | Stock quotes, after their review |
FRED_API_KEY | FRED |
BLS_API_KEY | BLS's higher limit, after its review |
NCBI_API_KEY | PubMed's higher limit, after its review |
SEMANTIC_SCHOLAR_API_KEY | Semantic Scholar's own limit |
STACKEXCHANGE_KEY | Stack Exchange's higher daily limit |
AIRNOW_API_KEY | AirNow air quality |
COMPANIES_HOUSE_API_KEY | Companies House |
STARTGG_TOKEN | start.gg |
TWITCH_CLIENT_ID, TWITCH_CLIENT_SECRET | Twitch, after its review |
ETHERSCAN_API_KEY | Etherscan, after its review |
AMILIA_API_TOKEN | Amilia (a partner token from Amilia) |
OPENROUTER_API_KEY, OPENROUTER_MODEL, WATCHER_LLM_MONTHLY_USD, WATCHER_LLM_OWNER_MONTHLY_USD | Learning recipes, judged conditions, page-change summaries, and suggestions on failed requests. The server's monthly cap defaults to $20, and each account's to $2 |
WATCHER_JUDGE_CALLS_PER_DAY | Judged checks a watcher may make a day. Defaults to 20 |
CAPTCHA_PROVIDER, CAPTCHA_API_KEY | Solving captchas: 2captcha, capsolver or anticaptcha |
WATCHER_CAPTCHA_UNREVIEWED_HOSTS | on (the default) solves captchas on any site; off only on WATCHER_REVIEWED_HOSTS |
WATCHER_REVIEWED_HOSTS | Hosts someone has reviewed, comma-separated. Steps may submit forms there, and with the switch off only these get captcha solves |
WATCHER_STEP_RUNS_PER_DAY, WATCHER_CAPTCHA_SOLVES_PER_DAY | Each account's daily caps on browser runs with steps (default 200) and captcha solves (default 100). 0 turns the thing off |