extract_ embedded_ state
Tapak moden menyirikan data yang dipaparkan antara mukanya terus ke dalam dokumen. Alat ini membacanya semula: satu pengambilan, nilai yang tepat, dan tiada model langsung dalam laluan ekstraksi.
Kes Penggunaan
Harga tepat daripada halaman yang dipapar dengan JavaScript
Harga, tahap stok dan ID datang daripada keadaan tapak itu sendiri dan bukan daripada model yang membaca teks yang dipapar, jadi tiada apa yang boleh direka.
Penyenaraian yang tidak dapat dilihat oleh scrape biasa
Hasil carian dan grid produk yang dipapar di sebelah klien selalunya sudah pun hadir dalam __NEXT_DATA__ atau muatan RSC pada respons pertama.
Lebih murah daripada ekstraksi LLM
2 credits berbanding 3 bagi extract_with_llm atau extract_structured, tanpa langkah inferens yang perlu ditunggu.
Mengaudit apa yang tapak terbitkan tentang dirinya
found melaporkan setiap sumber keadaan pada halaman dan saiznya, yang selalunya lebih banyak daripada yang ditunjukkan antara muka.
Endpoint
/api/v1/tools/extract_embedded_stateParameters
Satu panggilan berkos 2 credits. Dengan escalate: true unjurannya ialah siling 7 credits; 5 credits peringkat peningkatan dicaj hanya apabila ambilan biasa disekat dan peringkat itu benar-benar berjalan. keys_only dan find berkos 2 credits yang sama.
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
url | string | Required | - | Halaman untuk membaca keadaan terbenam. Example: https://example.com/products/widget |
path | string | Optional | - | Memulangkan satu subpohon dan bukan keseluruhan muatan. Hanya kunci bertitik dan indeks tatasusunan - ini bukan JSONPath, jadi tiada kad liar, penapis, hirisan atau penurunan rekursif. Laluan yang tidak dapat diselesaikan dipulangkan sebagai 400 yang menamakan kunci yang ada di tempat ia berhenti, dan tidak mengenakan credits. Example: next_data.props.pageProps |
user_agent | string | Optional | - | Menggantikan User-Agent yang dihantar kepada sasaran. Permintaan kekal ditandatangani sebagai CrawlForge; tandatangan itu meliputi authority, bukan pengepala ini. Example: MyCompanyBot/1.0 |
respect_robots | boolean | Optional | true | Menghormati robots.txt tapak sasaran. Dibiarkan pada `true`, laluan yang tidak dibenarkan untuk `CrawlForge` ditolak dengan 403 sebelum apa-apa diambil dan tiada credits dikenakan. Tetapkan kepada `false` hanya untuk sasaran yang anda ada perjanjian sendiri dengannya - respons kemudiannya membawa entri `warnings` dan penggantian itu direkodkan terhadap API key anda. Example: true |
timeout | number | Optional | 20000 | Had masa pengambilan dalam milisaat, antara 1000 dan 60000. Muatan keadaan selalunya bersaiz megabait, jadi nilai lalai di sini lebih tinggi daripada alat ekstraksi yang lebih ringan. Example: 20000 |
keys_only | boolean | Optional | false | Kembalikan `keys` dan bukan `data`: bentuk data yang dipilih (selepas `path`, jika diberi) sedalam dua aras, setiap daun dilabel `object`, `array(<n>)`, `string`, `number`, `boolean` atau `null`, dan tatasusunan yang dipilih ditunjukkan sebagai `{ length, first }` dengan bentuk unsur pertamanya. `found` dan `bytes` tidak berubah. Satu panggilan murah menunjukkan `path` mana yang patut diminta sebelum anda menarik muatan bersaiz berbilang megabait; kosnya 2 credits yang sama. Example: true |
find | string | Optional | - | Kembalikan `matches` dan bukan `data`: setiap sifat dengan nama kunci ini (tidak peka huruf besar-kecil) di mana-mana dalam data yang dipilih (selepas `path`), mengikut susunan dokumen, setiap satu sebagai {path, preview} dengan 200 aksara pertama nilainya - paling banyak 50, bersama `matches_total` dan `matches_truncated`. Setiap laluan padanan sudah bermula dengan `path`, jadi ia boleh dihantar semula terus sebagai `path`. Temui di mana sesuatu medan berada tanpa memuat turun muatan. Tidak boleh digabungkan dengan keys_only Example: specialty |
raw | boolean | Optional | false | Turut simpan tatasusunan devalue __NUXT_DATA__ yang belum dinyahkod di bawah json_scripts, di sebelah nuxt_data yang telah dinyahkod. Lalai: false Example: true |
escalate | boolean | Optional | false | Pilih untuk menyertai satu percubaan semula automatik melalui pelayar stealth apabila ambilan biasa menemui dinding dan bukan halaman — halaman cabaran Cloudflare, Amazon, DataDome, PerimeterX, Akamai atau Vercel, 403, 429 atau 444 semata-mata, atau cengkerang kosong yang tidak membawa keadaan. Ambilan biasa sentiasa berjalan dahulu; 404 atau 5xx tidak pernah ditingkatkan. HTML yang dipaparkan melalui penghurai yang sama, jadi respons mempunyai bentuk yang sama, ditambah `escalated` (setiap kali parameter ini ditetapkan) dan `stealth: { engine, vendor_detected }` apabila paparan itu berjalan. Peningkatan ini menggunakan semula laluan stealth yang sama seperti [stealth_mode](/docs/api-reference/tools/stealth-mode) dan pintu robots.txt yang sama, dan tidak menambah sebarang pengendalian baharu terhadap pertahanan bot; dinding yang turut menolak paparan itu tetap kembali sebagai halaman disekat, tanpa caj. Menambah 5 credits, dicaj hanya apabila paparan itu benar-benar berjalan. Membaca pemboleh ubah global `window` (`window_state`) hanya tersedia pada pelayan MCP: paparan API ini mengembalikan HTML. Example: true |
escalate_engine | string | Optional | playwright | Enjin pelayar bagi peringkat peningkatan: "playwright" (lalai) atau "camoufox" (berasaskan Firefox, ketahanan pengesanan yang lebih kuat; tersedia hanya di tempat ia dipasang pada backend). Diabaikan melainkan `escalate` ialah `true` dan ambilan biasa disekat. Example: camoufox |
wait_for | number | Optional | - | Masa menunggu tambahan selepas halaman dimuatkan dalam paparan yang ditingkatkan, dalam milisaat (0-30000), untuk keadaan yang ditulis oleh halaman selepas DOMContentLoaded. Dihantar kepada paparan stealth; diabaikan melainkan `escalate` ialah `true` dan ambilan biasa disekat. Example: 2000 |
max_inline_chars | number | Optional | 40000 | Ambang saiz sebaris, dalam aksara JSON hasil (1,000-10,000,000). Melebihinya, hasil penuh disimpan selama 1 jam dan respons mengekalkan `url`, `path`, `bytes`, `found` dan `data_keys` (kunci aras atas `data`, atau `array(<n>)`), serta `preview` — permulaan JSON yang diformat, dipotong pada sempadan baris supaya tiada nilai yang terbelah — `result_handle`, `total_chars` dan `truncated: true`. Keseluruhan respons kekal dalam saiz ini. Baca mana-mana medan salinan tersimpan dengan `json_path` [read_result](/docs/api-reference/tools/read-result), contohnya `data.next_data.props`, dengan 1 credit setiap panggilan. Example: 40000 |
Apa yang dibacanya
Setiap sumber yang dibawa halaman disenaraikan dalam found dan dikunci dalam data mengikut namanya. Pemboleh ubah global yang bukan JSON biasa dibaca sebagai literal JavaScript yang dinilai secara statik - objek, tatasusunan, rentetan, nombor dan fungsi satu-return Nuxt 2 - dan tiada kod halaman yang pernah dijalankan; apa-apa yang memanggil kod atau membaca pemboleh ubah lain dinamakan dalam warnings.
next_data-__NEXT_DATA__Next.js.next_f- baris flight React Server Component (self.__next_f), dikunci mengikut id baris, dengan rujukan$<id>antara baris diselesaikan di tempatnya (paling banyak menggandakan muatan).data_rows- indeks barisnext_fyang membawa data dan bukan markup, terbesar dahulu, setiap satu{ id, bytes, keys, length }. Data produk dan senarai biasanya terdapat dalam baris ini; baca satu denganpath: "next_f.<id>".nuxt-__NUXT__Nuxt 2;nuxt_data-__NUXT_DATA__Nuxt 3, dinyahkod daripada tatasusunan indeksnya kepada objek biasa.sveltekit_data- datakit.startSvelteKit, satu entri bagi setiap nod laluan, susun atur akar dahulu.yt_initial_datadanyt_initial_player_response-ytInitialDatadanytInitialPlayerResponseYouTube.apollo_state,apollo_ssr_transport,initial_state,preloaded_state,preloaded_data,remix_context(__remixContext),tgt_data(__TGT_DATA__),pws_data(__PWS_DATA__),server_data(__SERVER_DATA__),app_state(__APP_STATE__),state(__STATE__) danglobal_data(__data__) - pemboleh ubah globalwindowApollo, gaya Redux dan lain-lain.inertia_page- JSONdata-pageInertia.shopify-ShopifyAnalytics.metadan skrip JSON produk Shopify. Harga meta ialah integer dalam unit kecil: 10500 ialah 105.00 dalammeta.currency.json_scripts- blok<script type="application/json">dan<script type="text/json">, setiap satu{ id, data }.json_attributes- atributdata-*yang memegang objek JSON bersaiz 2 KB atau lebih, setiap satu{ tag, attribute, id, data }.
Cari laluan
Pada muatan berbilang megabait, minta kunci yang anda mahu dan bukan datanya. find mencari seluruh muatan, atau hanya di dalam path apabila anda menghantarnya, dan memulangkan tempat kunci itu muncul bersama permulaan setiap nilai.
curl -X POST https://crawlforge.dev/api/v1/tools/extract_embedded_state \
-H "X-API-Key: cf_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"path": "yt_initial_player_response",
"find": "viewCount"
}'Respons find
matches menggantikan data. Setiap path sudah bermula dengan path yang anda hantar, jadi hantar semula terus sebagai path dalam panggilan seterusnya untuk mendapatkan nilai penuh. matches_total mengira setiap padanan; matches_truncated ialah true apabila lebih daripada 50 yang dipulangkan ditemui. Padanan yang ditanda addressable: false berada di bawah kunci yang mengandungi . atau [, yang tidak dapat dieja oleh laluan.
{
"success": true,
"data": {
"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"found": [
{ "name": "yt_initial_data", "variable": "ytInitialData", "bytes": 21239 },
{ "name": "yt_initial_player_response", "variable": "ytInitialPlayerResponse", "bytes": 8076 }
],
"path": "yt_initial_player_response",
"bytes": 8076,
"matches": [
{
"path": "yt_initial_player_response.videoDetails.viewCount",
"preview": "\"1822707973\""
},
{
"path": "yt_initial_player_response.microformat.playerMicroformatRenderer.viewCount",
"preview": "\"1822707973\""
}
],
"matches_total": 2,
"matches_truncated": false,
"warnings": []
},
"credits_used": 2,
"credits_remaining": 996,
"processing_time": 640
}Contoh Permintaan
cURL - Baca keseluruhan keadaan
curl -X POST https://crawlforge.dev/api/v1/tools/extract_embedded_state \
-H "X-API-Key: cf_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/products/widget"
}'TypeScript - Hadkan dengan path
// npm install crawlforge-sdk
import { CrawlForge, ValidationError } from 'crawlforge-sdk';
const client = new CrawlForge({ apiKey: process.env.CRAWLFORGE_API_KEY });
try {
const result = await client.extractEmbeddedState({
url: 'https://example.com/products/widget',
// Dotted keys and array indexes. Not JSONPath: no wildcards or filters.
path: 'next_data.props.pageProps',
});
// result.data is untyped in crawlforge-sdk 0.1 — its shape is the Response Example below.
const { found, data } = result.data as {
found: { name: string; variable: string; bytes: number }[];
data: { product: { price: number } };
};
// Every state source on the page, largest first, whether or not it was scoped.
for (const source of found) {
console.log(source.name, source.variable, source.bytes);
}
// The values are the site's own, so they can be used as they are.
console.log(data.product.price);
} catch (err) {
// A path that does not resolve is a 400 naming the keys that were available.
if (err instanceof ValidationError) {
console.error(err.message);
} else {
throw err;
}
}Python - Temui dahulu, kemudian hadkan
# pip install crawlforge
from crawlforge import CrawlForge
client = CrawlForge() # reads CRAWLFORGE_API_KEY
# 1. Discover what the page carries. Nothing is truncated, so this can be big.
discovery = client.extract_embedded_state(
url='https://example.com/products/widget',
)
# discovery.data is a plain dict — its shape is the Response Example below.
for source in discovery.data['found']:
print(source['name'], source['variable'], source['bytes'])
# This tool's warnings live inside data, next to the state itself.
for warning in discovery.data['warnings']:
print('warning:', warning)
# 2. Ask again for just the branch you want.
scoped = client.extract_embedded_state(
url='https://example.com/products/widget',
path='next_data.props.pageProps.product',
)
print(scoped.data['bytes'], 'bytes')
print(scoped.data['data'])Contoh Respons
{ "success": true, "data": { "url": "https://example.com/products/widget", "found": [ { "name": "next_data", "variable": "__NEXT_DATA__", "bytes": 125 } ], "path": null, "bytes": 139, "data": { "next_data": { "buildId": "KfC_3GF1zuM", "props": { "pageProps": { "product": { "sku": "WID-9001", "price": 149.99, "currency": "USD", "inStock": true } } } } }, "warnings": [] }, "credits_used": 2, "credits_remaining": 998, "processing_time": 980}data.foundSetiap sumber keadaan pada halaman, dengan objek asal ia dibaca dan saiz bersirinyadata.pathLaluan yang digunakan, atau null apabila keseluruhan muatan dipulangkandata.bytesSaiz bersiri bagi apa yang dipulangkan - selepas dihadkan, apabila path diberikandata.dataKeadaan itu sendiri, diindeks mengikut nama sumberdata.warningsSumber yang hadir tetapi tidak boleh dihuraikan sebagai JSON, dan petunjuk saiz yang mencadangkan penggunaan pathPengendalian Ralat
Parameter tidak sah (400 Bad Request)
VALIDATION_ERROR, dengan masalahnya dalam details: contohnya find dihantar bersama keys_only - setiap satu menggantikan data dengan jawapannya sendiri, jadi hantar satu bagi setiap panggilan - atau find yang kosong atau melebihi 100 aksara. Tiada apa-apa diambil dan tiada credits dikenakan.
Laluan tidak dapat diselesaikan (400 Bad Request)
path tidak wujud dalam keadaan yang diekstrak. Mesejnya menamakan tempat ia berhenti dan kunci yang ada di situ, jadi kesilapan taip boleh terus dibetulkan. Tiada credits dikenakan. Jalankan panggilan sekali tanpa path untuk melihat apa yang sebenarnya dibawa oleh halaman itu.
Disekat oleh robots.txt (403 Forbidden)
robots.txt tapak sasaran tidak membenarkan laluan ini untuk CrawlForge. Tetapkan respect_robots: false untuk menggantikannya jika anda mempunyai perjanjian sendiri dengan sasaran - penggantian itu direkodkan terhadap API key anda. Penggantian ini tidak sampai kepada hos dalam senarai keluar kekal CrawlForge, yang ditolak apa pun nilai respect_robots.
Respons terlalu besar (413 Payload Too Large)
HTML halaman melebihi had badan 25MB. Had itu dikenakan pada halaman seperti yang dihidangkan, bukan pada keadaan yang diekstrak daripadanya. Tiada apa-apa dikenakan.
Sasaran tidak menjawab (504 Gateway Timeout)
Tapak itu tidak menjawab dalam timeout. Halaman yang sarat keadaan adalah besar; naikkan timeout ke arah siling 60000 sebelum menganggapnya sebagai kegagalan. Tiada apa-apa dikenakan.
Halaman disekat (502 Bad Gateway)
Ambilan biasa menemui halaman cabaran pertahanan bot (BLOCKED, dengan vendor dalam blocked) atau cengkerang kosong tanpa keadaan (UNUSABLE_DOCUMENT). Tiada caj dikenakan, dan mesejnya menamakan langkah seterusnya: jalankan semula dengan escalate: true. Jika escalate: true sudah ditetapkan, ralat yang sama membawa escalated: true — paparan stealth juga ditolak — dan tiada caj dikenakan.
Backend Peningkatan Tidak Dikonfigurasikan (503 TOOL_NOT_AVAILABLE)
escalate: true menjalankan peringkat stealth-nya pada backend pelaksanaan CrawlForge. Apabila backend itu tidak dikonfigurasikan, peringkat itu mengembalikan 503 dan tiada credits dicaj.
Alat Berkaitan
Sedia membaca data halaman itu sendiri? Daftar secara percuma dan dapatkan 1,000 credits.