npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ikman-api-client

v2.2.1

Published

Complete API client for ikman.lk - search listings, read individual ads, batch processing, filtering, and caching

Readme

ikman-api-client

✨ A modern Node.js + TypeScript-friendly client for ikman.lk.

Built for both simple scripts and serious data workflows:

  • Fast keyword search with reliable sorting
  • Advanced filtering (price/location/category)
  • Duplicate detection + canonicalization
  • Plugin pipeline for custom transforms/ranking
  • Streaming pagination for memory efficiency
  • Analytics export (csv, jsonl, parquet)
  • Smart local caching for repeated runs

npm version License: MIT Node.js TypeScript Plugins Streaming Export Cache


📚 Table of Contents


🚀 Why This Package

ikman-api-client gives you a clean API over ikman search pages, with practical features that reduce manual work:

  • No manual HTML parsing in your app
  • Strong defaults with customizable options
  • Works for quick scripts and analytics pipelines
  • Typed API surface for safer developer experience
  • CLI support for non-dev workflows

📦 Installation

npm install ikman-api-client

Install globally for CLI usage:

npm install -g ikman-api-client

⚡ Quick Start

import { search } from 'ikman-api-client';

const ads = await search('pixel phone', {
  maxPages: 5,
  sortBy: 'price-asc',
  minPrice: 50000,
  maxPrice: 250000,
  location: 'Colombo',
  dedupe: true,
  cache: true,
  cacheTTL: 3600,
  verbose: true
});

console.log(`Found: ${ads.length}`);
console.log('Top result:', ads[0]?.title, ads[0]?.price);

🧠 Core Concepts

Reliable Sorting

price-asc and price-desc are reinforced client-side to keep ordering stable even if upstream sort is inconsistent.

Dedupe + Canonicalization

Duplicates are detected from canonical fields:

  • normalized title
  • normalized location
  • numeric price

Enabled by default with dedupe: true.

Plugin Pipeline

Add custom ad transforms and result transforms via plugins.

Caching

File-based cache improves repeated searches.

  • cache (boolean)
  • cacheTTL (seconds)
  • cacheDir (directory)

🧩 TypeScript-First API

All types are provided in src/types.d.ts.

search / searchListings

Returns all results in one array.

import { search, SearchOptions } from 'ikman-api-client';

const options: SearchOptions = {
  maxPages: 20,
  respectAccessLimit: true,
  timeout: 90000,
  retries: 3,
  sortBy: 'price-desc',
  minPrice: 100000,
  maxPrice: 2000000,
  location: 'Colombo',
  category: 'Cars',
  dedupe: true,
  plugins: [],
  cache: true,
  cacheDir: '.ikman-cache',
  cacheTTL: 3600,
  saveToFile: false,
  fileName: 'ikman_results.json',
  verbose: true,
  includeRaw: false,
  delay: { min: 1000, max: 2000 }
};

const rows = await search('hybrid car', options);

searchPages

Streams one page at a time (memory efficient):

import { searchPages } from 'ikman-api-client';

for await (const page of searchPages('apartment', {
  maxPages: 10,
  sortBy: 'price-asc',
  location: 'Kandy',
  dedupe: true,
  verbose: false
})) {
  console.log('Page size:', page.length);
}

getSearchSummary

Quick metadata for total and accessible result counts:

import { getSearchSummary } from 'ikman-api-client';

const summary = await getSearchSummary('scooter', {
  sortBy: 'relevance',
  maxPages: 1
});

console.log(summary.total_count, summary.max_accessible_pages);

getAd / getAdDetails

Get full details for one listing:

import { getAd } from 'ikman-api-client';

const ad = await getAd('https://ikman.lk/en/ad/example-slug', {
  timeout: 30000,
  retries: 3,
  verbose: true,
  includeRaw: false
});

console.log(ad.title, ad.price, ad.images.length);

batch / processAdsBatch

Process multiple ad URLs with concurrency:

import { batch } from 'ikman-api-client';

const { results, errors, stats } = await batch([
  'https://ikman.lk/en/ad/example-1',
  'https://ikman.lk/en/ad/example-2'
], {
  concurrency: 3,
  delay: 1000,
  saveToFile: false,
  fileName: 'ikman_batch_results.json',
  verbose: true
});

console.log(stats, results.length, errors.length);

getImagesFromUrls

Extract images from multiple URLs:

import { getImagesFromUrls } from 'ikman-api-client';

const payload = await getImagesFromUrls([
  'https://ikman.lk/en/ad/example-1',
  'https://ikman.lk/en/ad/example-2'
], {
  concurrency: 2,
  delay: 500,
  verbose: true
});

console.log(payload.all_images.length);

🔌 Plugin Examples

Built-in plugins

import { search, plugins } from 'ikman-api-client';

const rows = await search('iphone', {
  maxPages: 5,
  plugins: [
    plugins.normalizeLocationPlugin(),
    plugins.scoreByPricePlugin({ min: 0, max: 500000 })
  ]
});

Custom plugin

import { search, SearchPlugin } from 'ikman-api-client';

const prioritizeUrgentPlugin: SearchPlugin = {
  name: 'prioritize-urgent',
  transformResults(rows) {
    return rows.sort((a, b) => Number(b.is_urgent) - Number(a.is_urgent));
  }
};

const rows = await search('laptop', {
  plugins: [prioritizeUrgentPlugin]
});

🛠️ Utilities

import { utils, Cache } from 'ikman-api-client';

utils.sortAds(rows, 'price-asc');
utils.filterAds(rows, { minPrice: 100000, location: 'Colombo' });
utils.dedupeAds(rows);

await utils.exportToCSV(rows, 'rows.csv');
await utils.exportToJSONL(rows, 'rows.jsonl');
await utils.exportToParquet(rows, 'rows.parquet');
utils.exportToJSON(rows, 'rows.json');

const cache = new Cache({ cacheTTL: 3600 });
console.log(cache.info());

🖥️ CLI Usage

Search

ikman search "pixel 8" --max-pages 5 --sort price-asc
ikman search "house" --location Colombo --min-price 5000000 --max-price 20000000
ikman search "car" --streaming --limit 100
ikman search "laptop" --format csv -o laptops.csv

Export for analytics

ikman export "car" --format csv --out cars.csv
ikman export "car" --format jsonl --out cars.jsonl
ikman export "car" --format parquet --out cars.parquet

Cache commands

ikman cache info
ikman cache clear
ikman cache dir

📈 Benchmarks

npm run benchmark:cold
npm run benchmark:warm
npm run benchmark:stream
npm run benchmark

With optional args:

node benchmarks/cold-cache.js "pixel" 8
node benchmarks/warm-cache.js "car" 10
node benchmarks/search-vs-pages.js "apartment" 20

📂 Local Examples

npm run example
npm run example:ad
npm run example:batch
npm run example:advanced
npm run example:images
npm run example:plugins

✅ Best Practices

  • Keep delay.min and delay.max at respectful values
  • Use searchPages() for large-volume workflows
  • Keep cache enabled for repeated queries
  • Add custom plugins for project-specific ranking/normalization
  • Verify target URLs before running batch modes

🤝 Contributing

See CONTRIBUTING.md.

📄 License

MIT — see LICENSE