On this page
JavaScript Code Examples
Node.js 18 and later ship a global fetch, so the first example below runs with no dependencies at all; Axios is worth adding only if you already use it elsewhere or want its interceptors. This page extracts the same single post three ways — a promise chain on fetch, the Axios equivalent with its own error shape, and an async/await wrapper you can drop into a project. Run all three server-side: a key shipped in browser code is a key anyone can read out of your bundle.
🚀 Using Fetch API
No dependencies, and the same code runs in Node and in a server-side runtime like Workers or Deno. The trap is that fetch rejects only on network-level failures: a 400 or a 429 resolves normally, so skipping the response.ok check means parsing an error body as though it were an extraction result. There is no default timeout either, so pass signal: AbortSignal.timeout(60000) on anything that runs unattended. On success, data.medias[0].variants holds the resolutions — take the one with is_default: true unless the user picked another, and treat a variant carrying both video_url and audio_url as a split stream you have to merge locally.
const apiUrl = "https://api.meowload.net/openapi/v1/extract/post";
const apiKey = "<your API key>";
fetch(apiUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${apiKey}`,
"Accept-Language": "en"
},
body: JSON.stringify({
url: "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
})
})
.then(response => {
if (!response.ok) {
// A 400 body carries code and retryable
return response.json().then(error => {
throw Object.assign(new Error(`${response.status}: ${error.message}`), {
code: error.code,
retryable: error.retryable === true
});
});
}
return response.json();
})
.then(data => {
// Both title and text are optional: sites with titles return title, others return text
console.log(`✅ Extraction successful! Site: ${data.site}, caption: ${data.title || data.text || "(none)"}`);
data.medias.forEach(media => {
console.log(`- ${media.media_type}: ${media.resource_url}`);
// Resolutions / audio tracks live in variants; both video_url and audio_url present means a split stream
for (const variant of media.variants ?? []) {
const split = variant.video_url && variant.audio_url ? " (needs merging)" : "";
console.log(` ${variant.quality_label ?? "default"}${split}`);
}
});
})
.catch(error => {
console.error(`❌ Request failed: ${error.message}`);
if (error.retryable) console.error(` Code ${error.code} is transient; retry later`);
});📦 Using Axios (Node.js)
Axios rejects on any non-2xx status, which is the mirror image of fetch: the failure branch moves entirely into .catch, and the API's error body arrives as error.response.data. Check that error.response exists first — for a DNS failure or a dropped connection it is undefined, and reading .data off it turns a network blip into a confusing TypeError. Axios has no timeout by default either, so pass timeout: 60000; and if you extract in bulk, a response interceptor that retries on retryable: true and backs off on 429 is the cheapest place to keep that logic, since one key is limited to 1,200 requests per minute.
npm install axiosconst axios = require('axios');
const apiUrl = "https://api.meowload.net/openapi/v1/extract/post";
const apiKey = "<your API key>";
axios.post(apiUrl, {
url: "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
}, {
headers: {
"Authorization": `Bearer ${apiKey}`,
"Accept-Language": "en"
}
})
.then(response => {
const data = response.data;
console.log(`✅ Extraction successful! Site: ${data.site}, caption: ${data.title || data.text || "(none)"}, media count: ${data.medias.length}`);
})
.catch(error => {
if (error.response) {
const { status, data } = error.response;
console.error(`❌ Request failed (${status}): ${data.message}`);
// 400 carries code and retryable; back off and retry on 429
if (data.retryable) console.error(` Code ${data.code} is transient; retry later`);
} else {
console.error(`❌ Network error: ${error.message}`);
}
});🎯 Using async/await
This is the version to keep in a project: one wrapper that either returns the parsed result or throws an Error carrying status, code and retryable, so every call site decides with a single if (error.retryable) whether a retry is worth attempting. Parsing the body before checking response.ok is deliberate — the error details live in that body — but wrap the json() call in a try if this runs behind a proxy that can answer with an HTML error page. From there result.medias is the list of downloadable items, and those URLs expire quickly: hand them straight to a download instead of storing them in a database for later.
async function extractPost(url, apiKey) {
const response = await fetch("https://api.meowload.net/openapi/v1/extract/post", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${apiKey}`
},
body: JSON.stringify({ url })
});
const data = await response.json();
if (!response.ok) {
// Surface code and retryable so the caller can decide whether to retry
throw Object.assign(new Error(data.message), {
status: response.status,
code: data.code,
retryable: data.retryable === true
});
}
return data;
}
// Usage
try {
const result = await extractPost("https://www.youtube.com/watch?v=dQw4w9WgXcQ", "<your API key>");
console.log(`✅ ${result.title || result.text || "(none)"}, media count: ${result.medias.length}`);
} catch (error) {
console.error(`Extraction failed: ${error.message}${error.retryable ? " (retry later)" : ""}`);
}If your key is new, start with the quickstart, which covers the three request headers and walks through a full response. The error codes page explains what each code means and which ones are worth a retry, while the API reference documents every field and lets you fire a test call from the browser. The same three patterns work against the other endpoints — the subtitle API returns every subtitle track with a download link per format, and the MCP server exposes the identical extraction over MCP if the caller is an AI agent rather than your own code.