The Path of Exile trade site uses a JSON-based query system to filter items. This document explains how the filtering works based on the Path of Building implementation.
The trade site supports two URL formats:
-
Query ID format:
https://www.pathofexile.com/trade/search/{league}/{queryId}- Example:
https://www.pathofexile.com/trade/search/Keepers/8rlgmrO8FV - The
queryId(e.g.,8rlgmrO8FV) is generated by the trade site when you submit a search - This ID can be used to retrieve the search results without re-submitting the query
- Example:
-
Encoded query format:
https://www.pathofexile.com/trade/search/{league}/?q={encodedQuery}- The
qparameter contains a URL-encoded JSON query object - This format allows direct sharing of search parameters
- The
The query is a JSON object with the following structure:
{
"query": {
"filters": {
"type_filters": {
"filters": {
"category": { "option": "armour.chest" },
"rarity": { "option": "nonunique" }
}
},
"misc_filters": {
"disabled": false,
"filters": {
"mirrored": false
}
},
"trade_filters": {
"filters": {
"price": {
"option": "chaos",
"max": 50
}
}
},
"socket_filters": {
"disabled": false,
"filters": {
"sockets": {
"min": 4,
"max": 6
},
"links": {
"min": 4,
"max": 6
}
}
},
"req_filters": {
"disabled": false,
"filters": {
"lvl": {
"max": 80
}
}
}
},
"status": { "option": "available" },
"stats": [
{
"type": "weight",
"value": { "min": 1000 },
"filters": [
{ "id": "stat_id_1", "value": { "weight": 1.5 } },
{ "id": "stat_id_2", "value": { "weight": 2.0 } }
]
}
]
},
"sort": {
"statgroup.0": "desc"
},
"engine": "new"
}- category: Item category (e.g.,
armour.chest,weapon.bow,accessory.ring) - rarity: Item rarity (
nonunique,unique, etc.)
The stats array contains stat groups that can be:
- type: "weight": Weighted search where each stat has a weight multiplier
- type: "and": All stats in the group must match
- type: "count": Count of matching stats
- type: "if": Conditional stat matching
Each stat filter has:
- id: The trade site's internal stat ID (fetched from
/api/trade/data/stats) - value: Can contain
min,max, orweightdepending on the filter type
- price: Maximum price in specified currency
- listing_time: How recently the item was listed
- sockets: Number of sockets (min/max)
- links: Number of linked sockets (min/max)
- lvl: Maximum level requirement
- mirrored: Whether to include mirrored items
- corrupted: Corruption status
- quality: Item quality percentage
Path of Building fetches stat definitions from the trade API:
-- Fetches from: https://www.pathofexile.com/api/trade/data/stats
local tradeStats = fetchStats()This provides a mapping between stat text (e.g., "+#% to Fire Resistance") and stat IDs used in queries.
-
Mod Weight Calculation: For each mod that can appear on the item:
- Creates a test item with that mod
- Calculates the stat difference compared to base item
- Assigns a weight based on configured stat priorities
-
Query Assembly:
- Sets item category based on slot type
- Adds stat filters with calculated weights
- Applies user options (price, level, sockets, etc.)
-
URL Encoding: The JSON query is URL-encoded using percent encoding:
function urlEncode(str) local charToHex = function(c) return s_format("%%%02X", string.byte(c)) end return str:gsub("([^%w_%-.~])", charToHex) end
From TradeQueryGenerator.lua:
local queryTable = {
query = {
filters = {
type_filters = {
filters = {
category = { option = "armour.chest" },
rarity = { option = "nonunique" }
}
}
},
status = { option = "available" },
stats = {
{
type = "weight",
value = { min = minWeight },
filters = { }
}
}
},
sort = { ["statgroup.0"] = "desc" },
engine = "new"
}
-- Add stat filters
for _, entry in pairs(self.modWeights) do
table.insert(queryTable.query.stats[1].filters, {
id = entry.tradeModId,
value = { weight = entry.weight }
})
end
local queryJson = dkjson.encode(queryTable)
local url = "https://www.pathofexile.com/trade/search/" .. league .. "/?q=" .. urlEncode(queryJson)When you have a URL with a query ID (like 8rlgmrO8FV), Path of Building extracts the query by:
- Fetching the HTML page:
https://www.pathofexile.com/trade/search/{league}/{queryId} - Extracting JSON from HTML: The page contains embedded JSON in a specific pattern:
local dataStr = response.body:match('require%(%["main"%].+ t%((.+)%);}%);}%);')
- Parsing the state: The JSON contains a
stateobject with the query:local data = dkjson.decode(dataStr) local query = { query = data.state }
The trade site organizes stats into categories:
- Explicit (index 2): Regular item mods
- Implicit (index 3): Base item implicits
- Corrupted (index 3): Corrupted item mods
- Scourge (index 6): Scourge mods
- Eater (index 3): Eater of Worlds mods
- Exarch (index 3): Searing Exarch mods
- Synthesis (index 3): Synthesis mods
- PassiveNode (index 2): Passive tree nodes (for cluster jewels)
Path of Building uses weighted searches to find items that improve your build:
-
Weight Calculation: Each stat is weighted based on:
- How much it improves your build's key stats (DPS, EHP, etc.)
- User-configured stat priorities
- The stat's value range
-
Minimum Weight: The query sets a minimum weight threshold:
local minWeight = currentStatDiff * 0.5
-
Sorting: Results are sorted by weighted sum in descending order:
"sort": { "statgroup.0": "desc" }
Path of Building maps item slots to trade site categories:
| Slot | Category |
|---|---|
| Body Armour | armour.chest |
| Helmet | armour.helmet |
| Gloves | armour.gloves |
| Boots | armour.boots |
| Shield | armour.shield |
| Amulet | accessory.amulet |
| Ring | accessory.ring |
| Belt | accessory.belt |
| 1H Weapon | weapon.one |
| 2H Weapon | weapon.two |
| Bow | weapon.bow |
| Staff | weapon.staff |
| Jewel | jewel or jewel.base |
| Abyss Jewel | jewel.abyss |
| Flask | flask |
-
Search:
POST https://www.pathofexile.com/api/trade/search/{realm}/{league}- Body: JSON query object
- Returns:
{ id: "queryId", result: ["itemHash1", ...], total: 1234 }
-
Fetch Items:
GET https://www.pathofexile.com/api/trade/fetch/{itemHashes}?query={queryId}- Returns: Full item details
-
Get Stats:
GET https://www.pathofexile.com/api/trade/data/stats- Returns: List of all available stat filters with IDs
Given: https://www.pathofexile.com/trade/search/Keepers/8rlgmrO8FV
- Extract league:
Keepers - Extract query ID:
8rlgmrO8FV - Fetch HTML:
GET https://www.pathofexile.com/trade/search/Keepers/8rlgmrO8FV - Extract JSON from HTML using regex pattern
- Parse
data.stateto get the query object - The query object contains all the filters that were used in the original search
- Trade Query Generator:
src/Classes/TradeQueryGenerator.lua - Trade Query Requests:
src/Classes/TradeQueryRequests.lua - Trade Query:
src/Classes/TradeQuery.lua - URL Encoding:
src/Modules/Common.lua(urlEncode function)