Function: Profiling and performance
Every function response includes profiling data with phase-level timing and resource usage.
Profiling
import createClient from 'microlink.io'
const microlink = createClient()
const { profiling } = await microlink.function('https://example.com', ({ page }) => page.title())
console.log(profiling)
// {
// phases: { install: 0, build: 120, spawn: 45, run: 890, total: 1055 },
// cpu: 234,
// memory: { total: 69996544, used: 2359296, heap: 4410880, external: 1742574 },
// size: 156
// }| Field | Description |
|---|---|
phases.install | Time spent installing npm dependencies (0 when none are used) |
phases.build | Time spent bundling the function code |
phases.spawn | Time spent starting the isolated process |
phases.run | Time spent executing the function |
phases.total | Wall-clock time from start to finish |
cpu | Peak CPU time in milliseconds |
memory.total | Resident memory of the sandbox, Node.js baseline included, in bytes |
memory.used | Resident memory attributable to your function, in bytes |
memory.heap | V8 heap in use, in bytes. The only field the memory limit bounds |
memory.external | Off-heap Buffer/ArrayBuffer memory, in bytes |
size | Bundled code size in bytes |
Use profiling to understand where time is spent. If install is high, your dependencies are being installed for the first time — subsequent runs use the cache. If run is high, the function itself is doing heavy work.
Plan limits
The function parameter is available on both free and pro plans:
| Free | Pro | |
|---|---|---|
| Timeout | 15 seconds | Up to 60 seconds |
| Memory | 64 MB | 128 MB |
| Code size | 1024 bytes | Unlimited |
| Concurrency | 1 in-flight per IP | Unlimited |
| Outgoing requests | Same-origin only | Unrestricted |
A free API key is enough to prototype workflows and run the examples in this guide;
headers, proxy, ttl and staleTtl are included. For production workloads that need more volume, use a paid plan.To authenticate, pass your API key:
import createClient from 'microlink.io'
const microlink = createClient({
apiKey: process.env.MICROLINK_API_KEY
})
const { value } = await microlink.function('https://example.com', ({ page }) => page.title())See the authentication and rate limit docs for endpoint and quota details.
When the page is fetched
A function-only request pays for the function and nothing else: normalized metadata is off by
default, and the page is resolved only when your code needs it.
| your function | what the request does |
|---|---|
never mentions page | nothing is fetched |
calls page.content(), page.extract() or page.metadata() | the page is fetched at the moment you call it |
drives the browser, such as page.click() or page.evaluate() | the page is loaded once and your function runs on it |
The fetch happens on the call, not before your function starts.
Destructure
page itself rather than its methods. ({ page }) => page.content() is answered from
fetched HTML with no browser, while ({ page: { content } }) => content() cannot be read ahead of
time and starts a full browser.Ask for meta explicitly when you want normalized metadata alongside the
function, or call page.metadata inside it to get the same data for one page load:
import createClient from 'microlink.io'
const microlink = createClient()
const { value } = await microlink.function(
'https://example.com',
async ({ page }) => (await page.metadata()).title
)
console.log(value)page.metadata() returns the same fields as meta.Compress large functions
Large function bodies are compressed before they are sent. The SDK handles this automatically —
microlink.function() compresses the code with brotli in Node.js and lz-string in browsers, so the call stays the same:import createClient from 'microlink.io'
const microlink = createClient()
const { value, profiling } = await microlink.function('https://example.com', ({ page }) => page.title())
console.log(profiling.size)If you call the API directly, prefix the compressed payload with the algorithm alias:
lz# for lz-string, br# for brotli, gz# for gzip. See the compression reference for details.Optimization checklist
- Leave metadata off — a function-only request already skips it. Ask for
meta: trueonly when you genuinely want it, since it is usually the largest cost in the request. - Use
page.title()andpage.$eval()instead ofpage.evaluate()when possible — they are faster and easier to debug. - Replace fixed waits like
page.waitForTimeout(3000)withpage.waitForSelector()— they resolve as soon as the element appears. - Check
profiling.phasesto find the bottleneck — a high install on first run is normal, but a high run means the function itself needs work. - Minimize dependencies — each
require()adds install and build time. Use only what you need.
See also
- Troubleshooting — error handling, resource errors, and debugging.
- Common caching patterns — reduce cost and improve response speed.
- Function reference — response shape, plan limits, and compression.