Pokemon IV scouting queue that receives webhooks from Golbat, filters by priority list and Koji geofences, and dispatches scout requests to Dragonite.
Requires Python 3.12+
# Recommended:
# Create virtual environment
py -3.12 -m venv .venv
# Activate (Windows)
.venv\Scripts\activate
# Activate (Linux/Mac)
source .venv/bin/activate
# Install dependencies
pip install -r requirements.txt
# Copy config files
cp .env.example .env
cp LazyIVQueue/config/example.config.json LazyIVQueue/config/config.json
# Only if using FILTER_WITH_GEOFENCE_FILE=TRUE instead of Koji:
cp LazyIVQueue/config/example.geofences.json LazyIVQueue/config/geofences.jsonLogging
LOG_LEVEL- Log level (default:INFO)LOG_FILE- Log to file (default:FALSE)
Server
LAZYIVQUEUE_HOST/LAZYIVQUEUE_PORT- Server bind address (default:0.0.0.0:7070)
Dragonite Scout API
DRAGONITE_API_BASE_URL- Dragonite Scout API endpoint (e.g.,http://127.0.0.1:7272)DRAGONITE_API_USERNAME/DRAGONITE_API_PASSWORD- Basic auth credentials (optional)DRAGONITE_API_KEY- API key auth (optional)DRAGONITE_BEARER_KEY- Bearer token auth (optional)
Auto Rarity
AUTO_RARITY- Enable dynamic rarity-based queueing (default:FALSE). See Auto Rarity section below
Koji Geofences
FILTER_WITH_KOJI- Enable geofence filtering via Koji (default:TRUE). Set toFALSEto skip Koji geofence checksKOJI_URL- Full Koji base URL (e.g.,http://koji.example.com:8080). Alternative to KOJI_IP/KOJI_PORTKOJI_IP/KOJI_PORT- Koji host and port (default:127.0.0.1:8080)KOJI_TOKEN- Koji bearer token for authenticationKOJI_PROJECT_NAME- Koji project name containing the geofences to useFILTER_WITH_GEOFENCE_FILE- Load geofences fromLazyIVQueue/config/geofences.jsoninstead of Koji (default:FALSE). Only takes effect whenFILTER_WITH_KOJI=FALSE— if both areTRUE, Koji wins and a warning is logged at startup. Copyexample.geofences.jsonto get started. BothPolygonandMultiPolygongeometries are supported, from either source
Security
ALLOWED_IPS- Comma-separated IPs allowed to POST webhooks (e.g.,127.0.0.1,192.168.1.100)HEADERS- Header auth (format:HeaderName: Value). Example Golbat config:
[[webhooks]]
url = "http://localhost:7070/webhook"
types = ["pokemon"]
headers = ["HeaderName: Value"]
/webhookaccepts"pokemon","pokemon_no_iv", and"pokemon_iv"interchangeably —"pokemon"is the combined superset of the other two, so listing it alone is sufficient if you prefer.pokemon_no_iv/pokemon_ivfire separately (initial sighting, then IV completion) if you'd rather be explicit. Both no-IV and IV-bearing encounters are required — no-IV feeds queueing and rarity census, IV feeds early-IV detection and queue removal.
ivlist- Priority list of Pokemon to scout forwild/nearby_stopseen_types"pokemon_id"- Match any form (e.g.,"1"matches Bulbasaur any form)"pokemon_id:form"- Match specific form only (e.g.,"3:0"matches Venusaur form 0)"pokemon_id:form:costume"- Match specific form AND costume (e.g.,"25:any:1"matches Pikachu any form, costume 1 only)"any"(case-insensitive) in the form or costume position means "no filter on this field" — needed to target a costume without narrowing form ("25:any:1"), or to be explicit about matching any form ("25:any", same as"25")- Match precedence is strict list order: the earliest entry in the list that matches a sighting wins, regardless of how specific it is compared to other matching entries later in the list — e.g. with
["25", "25:0"], a form-0 sighting of Pokemon 25 matches"25"(index 0), not"25:0"(index 1) - Example:
["Pokemon A", "Pokemon B:0", "Pokemon C:any:1"]- A is top priority, then B form 0, then C any form costume 1 only
celllist- Priority list fornearby_cellseen_type (same format as ivlist)- Celllist entries are always processed before ivlist entries, so only insert really important ones here
- Uses 9x9 pattern (9 coordinates) to cover S2 level-15 cell
denylist- Block list of Pokemon to never scout (same format as ivlist/celllist)- Applies to all seen_types — denylisted Pokemon are silently dropped before queueing
- When
AUTO_RARITY=TRUE, the denylist persists across reloads and prevents rare-but-unwanted Pokemon from being queued - Empty list disables the feature
scout.concurrency- Max concurrent scout requests - Should match the number of scouts you have set in Dragonitescout.timeout_iv- Seconds to wait for IV data before removing from queue - Liberating the scout to work (default: 180)scout.wild_scout_delay- Seconds to holdwild/nearby_stopentries before scouting (default:0, disabled). Set to15if your scanner sends encounters immediately — IVs that arrive naturally during the hold are recorded aswild_earlyand no scout is wastedgeofences.expire_cache_seconds- How long to cache geofences before expiring (default: 1800)geofences.refresh_cache_seconds- How often to refresh geofences from Koji (default: 1800)auto_rarity- Dynamic rarity settings (whenAUTO_RARITY=TRUE):calibration_minutes- Minutes to collect spawn data before rankings are used (default: 5)iv_threshold- Queue Pokemon with rarity rank below this (default: 50, lower = rarer)cell_threshold- Cell scout threshold (default: 20)ranking_interval_seconds- How often to recalculate rankings (default: 120)cleanup_interval_seconds- How often to remove despawned Pokemon from tracking (default: 60)
When AUTO_RARITY=TRUE, LazyIVQueue dynamically tracks Pokemon spawn rarity and queues rare Pokemon automatically.
- Spawn Tracking: Every non-IV spawn received on
/webhookis automatically recorded for rarity tracking — no separate census webhook needed - Rarity Tracking: The system tracks active spawns per area (or globally if Koji disabled)
- Calibration: During the calibration period, only ivlist/celllist Pokemon are queued
- Dynamic Queueing: After calibration, Pokemon with rarity rank below the threshold are queued
- Tier 0 (0-999): VIP lists (celllist + ivlist) - position in list determines sub-priority
- Tier 1000+: auto_rarity entries - 1000 for unknown, 1000+rank for ranked Pokemon
This ensures ivlist/celllist entries ALWAYS take priority over auto_rarity entries.
A single webhook configuration covers both scouting and rarity tracking — see the example under Security above (types = ["pokemon", "pokemon_no_iv", "pokemon_iv"]). No separate census webhook is needed.
python -m LazyIVQueue.lazyivqueuecp example.docker-compose.yml docker-compose.yml
docker-compose up -d --buildPOST /webhook- Receives Pokemon webhooks from Golbat (ivlist/celllist filtering + rarity census tracking)GET /health- Health checkGET /stats- Queue, scout, and rarity statistics — includes IV/hour rates (nearby_cell, normal, combined)GET /queue- Queue preview (next N entries, use?count=N)GET /rarity- Auto Rarity rankings per area (use?area=AreaName&limit=100)GET /config- Current configuration summaryPOST /reload- Hot-reload config.json values without restarting
# Health check
curl -s http://localhost:7070/health
# Per-type session breakdown (queued / matches / early_iv / timeouts)
curl -s http://localhost:7070/stats | jq '.queue.session | {queued: .total_queued, matches: .total_matches, early_iv: .total_early_iv, timeouts: .total_timeouts}'
# Full stats (queue + scout coordinator + rarity)
curl -s http://localhost:7070/stats | jq .
# Preview next 20 queue entries
curl -s "http://localhost:7070/queue?count=20" | jq .
# Rarity rankings for a specific area (top 50)
curl -s "http://localhost:7070/rarity?area=CityCenter&limit=50" | jq .
# Current config summary
curl -s http://localhost:7070/config | jq .
# Hot-reload config.json
curl -X POST http://localhost:7070/reloadAdd
-H "HeaderName: Value"to any request if your server uses header auth.
The /reload endpoint allows you to update config.json values without restarting the service.
Reloadable settings:
ivlist,celllist,denylist- Priority/block listsauto_raritysettings - thresholds, intervalsscout.concurrency,scout.timeout_iv,scout.wild_scout_delay- Scout settingsgeofencescache settings
Requires restart:
- Server host/port (
.env) - Dragonite API settings (
.env) - Koji credentials (
.env) AUTO_RARITY,FILTER_WITH_KOJI(.env)LOG_LEVEL,LOG_FILE(.env)
[+]- Pokemon added to queue[>]- Scout request sent to Dragonite[<]- IV match found (scout successful) or Early IV (received before scout)[x]- Scout timeout (no IV received within timeout_iv seconds)[!]- Scout request failed
[*]- Census status during calibration / New area discovered[~]- Census status after calibration / Census cleanup