Search AgentPowers through its JSON search endpoint and return normalized records with marketplace metadata, provenance, and nullable fields represented explicitly as null. It supports agent or skill filtering, client-side fallback when server-side type filtering fails, and pagination deduplication.
Use Cases
- Find skills matching a keyword such as Git
- Find agents matching a browser or automation query
- Collect marketplace metadata with normalized null values
- Page through searches exceeding one response
Automation Flow
- Build
https://api.agentpowers.ai/v1/search?q={encodeURIComponent(query)}&limit={limit}&offset={offset}; append&type={type}when server-side filtering is required. - Goto the URL and run this extractor on the JSON response page. When
type=agentreturns no records unexpectedly, repeat once withouttypeand let the extractor filter records locally.
(()=>{
const text=document.body?.innerText||document.body?.textContent||'';
let root;
try{root=JSON.parse(text)}catch(e){return {parse_error:String(e),query:new URLSearchParams(location.search).get('q'),results:[]}};
const raw=[];
const walk=x=>{
if(Array.isArray(x)){x.forEach(walk);return}
if(!x||typeof x!=='object')return;
if(typeof x.slug==='string'&&(typeof x.title==='string'||typeof x.name==='string'))raw.push(x);
Object.values(x).forEach(v=>{if(v&&typeof v==='object')walk(v)});
};
walk(root);
const params=new URLSearchParams(location.search);
const norm=v=>v===undefined||v===null||(typeof v==='string'&&!v.trim())?null:v;
const pick=(o,keys)=>{for(const k of keys)if(o[k]!==undefined&&o[k]!==null)return o[k];return null};
const seen=new Set();
const items=raw.filter(o=>{
const requested=params.get('type');
return requested?norm(pick(o,['type','kind']))===requested:true;
}).filter(o=>{
const key=String(o.slug)+'\u0000'+String(pick(o,['type','kind']));
if(seen.has(key))return false;
seen.add(key);return true;
}).map(o=>{
const author=pick(o,['author','creator','owner']);
return {
slug:norm(o.slug),
title:norm(pick(o,['title','name'])),
description:norm(pick(o,['description','summary'])),
category:norm(o.category),
type:norm(pick(o,['type','kind'])),
price:norm(pick(o,['price','cost'])),
price_cents:norm(o.price_cents),
currency:norm(o.currency),
version:norm(o.version),
security_status:norm(pick(o,['security_status','securityStatus','security','ap_security_status','source_security'])),
security_score:norm(o.ap_security_score),
install_count:norm(pick(o,['install_count','installCount','installs','source_installs'])),
download_count:norm(pick(o,['download_count','downloadCount','downloads','source_downloads'])),
view_count:norm(pick(o,['view_count','viewCount','views'])),
rating:norm(pick(o,['rating','averageRating','avgRating','source_rating'])),
rating_count:norm(pick(o,['rating_count','ratingCount'])),
author:norm(typeof author==='object'?pick(author,['name','username','handle','slug']):author)||norm(o.owner_display_name),
source:norm(pick(o,['source','provider','origin'])),
source_url:norm(o.source_url),
source_installs:norm(o.source_installs),
source_stars:norm(o.source_stars)
};
});
return {query:params.get('q'),type:params.get('type')||null,limit:Number(params.get('limit')),offset:Number(params.get('offset')),count:items.length,items};
})()- For additional pages, increase
offsetbylimit, run the same extractor, concatenateitems, and deduplicate bytypeplusslug.
Params
| Param | What it does | Example value |
|---|---|---|
| query | Required search text, 1–200 characters | browser automation |
| type | Optional server-side type filter; also applied client-side | agent |
| limit | Results per page, 1–100 | 25 |
| offset | Zero-based pagination offset | 0 |
Possible Friction Points
type=agentreturns no records while the unfiltered response contains agents → retry the same URL withouttypeand retain only records whose normalized type isagent.- An offset returns the same first-page records → deduplicate by
typeplusslug, then stop or try another offset only when more unique results are required. - API response uses a different top-level result container → run the recursive extractor; it searches all nested objects for slug/title records.
- Nullable or blank security, rating, author, or source fields occur → preserve them as explicit
nullvalues throughnorm. - API rejects an empty or overlong query → URL-encode the query and keep it between 1 and 200 characters.