छोटे VPS पर Moli headless browser कैसे चलाएँ
Moli install करें, CDP को loopback पर serve करें और agent को जोड़ें। जानें कि बिना Chromium wrapper के यह कहाँ रुकता है और किन pages पर Chrome चाहिए।
छोटे VPS पर चलने वाला headless browser
Moli AI agents के लिए headless browser है। यह इतना छोटा है कि उस VPS पर self-host किया जा सकता है जहाँ headless Chrome के लिए पर्याप्त संसाधन नहीं होंगे। यह Rust में लिखा गया browser engine है, Chromium का wrapper नहीं। यह Chrome DevTools Protocol (CDP) पर response देता है, जिस protocol से आपकी automation library पहले से संवाद करती है। आप एक binary install करते हैं, moli serve चलाते हैं, फिर Playwright या अपने agent code को http://127.0.0.1:9222 पर point करते हैं।
कुछ भी install करने से पहले इस trade-off को समझ लें। Project अपना scope स्पष्ट रूप से बताता है: GUI browser नहीं है, GPU compositor नहीं है, Chrome के साथ pixel-for-pixel parity नहीं है, और Canvas या media playback के लिए high fidelity नहीं है। जिन pages को इन सुविधाओं की आवश्यकता होगी, वे fail होंगे। Playwright के साथ real Chrome fallback बना रहता है। अंतिम section में बताया गया है कि किन pages के लिए इसकी आवश्यकता है।
नीचे दिए गए सभी commands project के README और उसकी published skill files से लिए गए हैं, जिन्हें August 2026 में check किया गया था। Charts में दिया गया हर number project द्वारा अपने engine के बारे में published figure है; यह इस site से लिया गया measurement नहीं है। प्रत्येक chart caption में यह स्पष्ट किया गया है। यदि आप अभी भी किसी engine का चयन कर रहे हैं, तो VPS पर agents के लिए headless browsers का विस्तृत survey alternatives को cover करता है।
headless Chrome इतनी memory का उपयोग क्यों करता है?
Chrome एक multi-process browser है। प्रत्येक tab और प्रत्येक cross-site iframe को अपना renderer process मिलता है। प्रत्येक renderer का अपना V8 heap और अपने graphics buffers होते हैं। यह design desktop के लिए सही है, क्योंकि एक crashed tab के कारण पूरी window बंद नहीं होती। 2 GB VPS पर इसका अर्थ है कि एक browse step में आपके वास्तविक application से भी अधिक memory लग सकती है।
इस project ने चार engines के साथ 192 mixed public URLs को crawl किया और परिणाम प्रकाशित किया।
इस चार्ट के पीछे का डेटा
[
{
"engine": "Moli",
"useful_pages": 103,
"median_rss_mib": 73
},
{
"engine": "Chrome Headless",
"useful_pages": 101,
"median_rss_mib": 773
},
{
"engine": "Lightpanda",
"useful_pages": 85,
"median_rss_mib": 40
},
{
"engine": "Obscura",
"useful_pages": 57,
"median_rss_mib": 39
}
]Chrome Headless ने 101 useful pages लौटाए और Moli ने 103 लौटाए। इसलिए उस sample में दोनों engines ने web के लगभग समान हिस्से को पढ़ा। अंतर memory में है: Chrome के लिए median RSS (resident set size, यानी process द्वारा RAM में वास्तव में रखी गई memory) 773 MiB था, जबकि Moli के लिए 73 MiB। यह दिशा विश्वसनीय है, क्योंकि यह process architecture से निकलती है। अपने pages के लिए exact ratio मानकर न चलें।
आपके लिए median महत्वपूर्ण संख्या नहीं है। Peak महत्वपूर्ण है। जब 2 GB box की memory समाप्त हो जाती है, तो kernel किसी एक process को चुनकर उसे kill कर देता है। इसका record dmesg -T या journalctl -k में दर्ज होता है:
Out of memory: Killed process 4211 (chrome) total-vm:2318936kB, anon-rss:1418324kB, file-rss:0kB, shmem-rss:0kB, UID:1000 pgtables:3540kB oom_score_adj:0आपका agent उस line को कभी नहीं देखता। उसे केवल ऐसा browser दिखाई देता है जो जवाब देना बंद कर चुका है। आम तौर पर यह page.goto: Page crashed जैसे Playwright error या closed target के रूप में दिखता है। उस error में memory का कोई उल्लेख नहीं होता। इसी कारण छोटे box पर agent के random failure होने पर सबसे पहले OOM (out of memory) killer की जाँच करनी चाहिए। Peak के आधार पर sizing करना वही प्रक्रिया है जो agent VPS के लिए RAM और CPU चुनना है।
Moli binary को एक निश्चित version पर install करें
Project GitHub releases पर एक shell installer और पहले से बने tarballs प्रकाशित करता है। August 2026 तक current release 1.0.1 है, जिसे 18 August 2026 को प्रकाशित किया गया था। इस guide में दिए गए benchmark figures project ने 0.1.1 पर मापे थे। इसलिए इन्हें आपके install किए गए build के बारे में पक्के वादे के बजाय engine के सामान्य व्यवहार का अनुमान मानें।
Version को pin करें। ऐसा installer जो हमेशा latest resolve करता है, अगले rebuild पर आपके agent को किसी अलग browser engine पर ले जाएगा। Browser behaviour में बदलाव ऐसी चीज है जिसे आप schedule करना चाहेंगे, न कि बाद में अचानक देखना।
Shell installer शुरुआत करने का तेज तरीका है। इसे चलाने से पहले पढ़ना उपयोगी है।
curl --proto '=https' --tlsv1.2 -fsSL \
-o /tmp/moli-installer.sh \
https://github.com/lexmount/moli/releases/download/v1.0.1/moli-installer.sh
less /tmp/moli-installer.sh
sh /tmp/moli-installer.shइसे चलाने से पहले script पढ़ें। यह छोटी है। यह आपके uname -m से एक archive चुनती है और फिर एक single binary को ~/.local/bin में unpack करती है। x86_64 पर यह moli-x86_64-unknown-linux-gnu.tar.gz लेती है और Arm server पर aarch64 archive लेती है। इसलिए Arm और x86 VPS plans दोनों शामिल हैं। किसी अन्य स्थान पर install करने के लिए MOLI_INSTALL_DIR set करें। ध्यान दें कि यह version के लिए क्या resolve करती है: script को fetch किए गए tag के बजाय newest release। पहली बार देखने के लिए यह ठीक है, लेकिन repeatable rebuild के लिए सही नहीं है।
इसलिए permanent installation के लिए installer जो करता है, वह manually करें और exact archive स्वयं specify करें। इससे binary को उस स्थान पर भी रखा जा सकता है जहाँ system service उसे access कर सके। साथ ही, downloaded script को shell में pipe करने की जरूरत नहीं रहती।
cd /tmp
curl --proto '=https' --tlsv1.2 -fsSLO \
https://github.com/lexmount/moli/releases/download/v1.0.1/moli-x86_64-unknown-linux-gnu.tar.gz
mkdir -p moli-pkg
tar -xzf moli-x86_64-unknown-linux-gnu.tar.gz -C moli-pkg --strip-components=1
sudo install -m 0755 moli-pkg/moli /usr/local/bin/moli
moli --versionmoli --version से pinned version print हो जाना ही पूरी जाँच है। Installer के तुरंत बाद moli: command not found का अर्थ है कि install directory आपके PATH में नहीं है। Installer उस directory का नाम बताने वाली एक line print करता है, जिसे आपको add करना होगा।
moli fetch से एक ही बार में extraction
Agent को browser से मिलने वाले कई काम इस प्रकार होते हैं: "इस URL को load करें और बताएं कि इसमें क्या लिखा है।" इसके लिए किसी server की जरूरत नहीं होती। moli fetch engine शुरू करता है, एक page load करता है, एक artifact को standard output पर लिखता है और exit हो जाता है। इसलिए calls के बीच memory में कुछ बना नहीं रहता।
moli fetch --dump markdown --wait-until networkidle https://example.com
moli fetch --dump semantic_tree_text --wait-selector "main" https://example.com
moli fetch --dump json --wait-until networkidle https://example.com > page.jsonपहला command page को Markdown के रूप में print करता है और इसकी शुरुआत # Example Domain से होती है। Markdown को model तक पहुँचाना सबसे कम लागत वाला विकल्प है, क्योंकि यह markup हटाकर केवल text रखता है। semantic_tree_text roles और structure बनाए रखता है। Navigation-heavy page पर यह उपयोगी है, जहाँ links prose जितने ही महत्वपूर्ण होते हैं। --dump json HTTP status और request trace देता है। इसलिए fetch खाली लौटने पर और कारण जानने की जरूरत होने पर इसका उपयोग करें।
Wait strategy तय करती है कि आपको content मिलेगा या empty shell। --wait-until networkidle network शांत होने पर लौटता है। --wait-until domstable DOM में बदलाव रुकने पर लौटता है। यह उस page के लिए बेहतर विकल्प है जो background में polling करता है और इसलिए कभी पूरी तरह शांत नहीं होता। --wait-selector आपके बताए हुए एक selector तक प्रतीक्षा करता है। यह एकमात्र strategy है जिसे fetch किए जा रहे page के बारे में कोई जानकारी होती है। इसलिए target ज्ञात होने पर यह सबसे reliable विकल्प है।
Screenshots और PDF के लिए वास्तविक layout चाहिए। Layout default रूप से off रहता है:
moli fetch --layout --dump screenshot https://example.com > page.png
moli fetch --layout --dump screenshot_full https://example.com > full-page.png
moli fetch --layout --dump pdf https://example.com > page.pdfREADME default layout policy को LayoutPolicy::Mock नाम देता है। इसमें geometry का अनुमान लगाया जाता है और कुछ paint नहीं किया जाता, क्योंकि layout और paint browser के महंगे हिस्से हैं। यही default कारण है कि ऊपर दिए गए memory figures वैसे दिखाई देते हैं। इसका अर्थ यह भी है कि empty PNG आम तौर पर missing --layout flag के कारण होता है, broken page के कारण नहीं।
Agent द्वारा खोजे गए URLs के लिए, न कि आपके चुने हुए URLs के लिए, --block-private-networks जोड़ें। किसी page पर पढ़े गए links को follow करने वाला agent cloud instance credentials के लिए http://169.254.169.254/ या localhost पर मौजूद ऐसे database port को fetch करने के लिए निर्देशित किया जा सकता है, जिसे कभी web के सामने expose करने का उद्देश्य नहीं था। यह flag private address space में navigation को अस्वीकार करता है, और --block-cidrs इसे और सीमित करता है। जब job एक page पढ़ने के बजाय crawling की हो, तो उस pipeline का ढाँचा self-hosted Firecrawl के विकल्प में बताया गया है। उससे पहले का चरण, यानी URLs खोजने का तरीका, agents के लिए SearXNG-आधारित search skill में बताया गया है।
CDP के माध्यम से agent को Moli से जोड़ें
कई चरणों में navigation और clicks करने वाले agent के लिए इसके बजाय server चलाएँ।
moli serve --host 127.0.0.1 --port 9222127.0.0.1 और port 9222 default हैं, इसलिए केवल moli serve चलाने पर भी यह केवल loopback पर bind होता है। फिर भी किसी permanent configuration में दोनों को स्पष्ट रूप से लिखें, क्योंकि आपकी service file पढ़ने वाले अगले व्यक्ति को default याद रखने की जरूरत नहीं होनी चाहिए।
Client को server से connect करने से पहले server जाँचें:
curl -s http://127.0.0.1:9222/json/versionसही server एक JSON object के साथ उत्तर देता है, जिसमें webSocketDebuggerUrl field होती है। CDP client इसी URL से attach होता है। curl: (7) Failed to connect to 127.0.0.1 port 9222: Connection refused का अर्थ है कि कोई process listen नहीं कर रहा है। इसलिए जिस terminal में आपने इसे शुरू किया था, उसे देखें या service बनने के बाद journalctl -u moli -n 50 चलाएँ। /json/list खुले targets की सूची देता है और /json/protocol उन domains की सूची देता है जिन्हें यह build लागू करता है। इससे पता चलता है कि जिस CDP method पर आप निर्भर हैं, वह यहाँ उपलब्ध है या नहीं।
Playwright अपना browser शुरू करने के बजाय उस endpoint से attach होता है:
import { chromium } from "playwright";
const browser = await chromium.connectOverCDP("http://127.0.0.1:9222");
const context = browser.contexts()[0];
const page = context.pages()[0] ?? await context.newPage();
await page.goto("https://example.com");
console.log(await page.locator("body").innerText());
await browser.close();महत्वपूर्ण line connectOverCDP है, chromium.launch() नहीं। यहाँ कोई child Chromium process नहीं है, इसलिए executablePath और सामान्य container flags जैसे --no-sandbox किसी process पर लागू नहीं होते। इसी कारण proxy, cookie और user-agent settings Moli server को उसके अपने flags के रूप में देनी होती हैं। पूरे Chrome protocol के बजाय CDP के चुने हुए हिस्से उपलब्ध होने की अपेक्षा रखें। Explicit unsupported-method error engine की सीमा बताता है, आपके code की bug नहीं।
दो server flags तय करते हैं कि agent क्या कर सकता है। --layout real geometry चालू करता है। Coordinate clicks और screenshots के लिए यही आवश्यक है। --resource optional images, fonts और media fetch करता है। इससे प्रत्येक page load पर bandwidth और memory की लागत बढ़ती है, इसलिए जब तक कोई page इसकी आवश्यकता साबित न करे, इसे बंद रखें। --profile-dir runs के बीच cookies और storage सुरक्षित रखता है। इसके बिना हर run disposable होता है।
इस चार्ट के पीछे का डेटा
[
{
"engine": "Moli",
"cdp_ready_ms": 34.85,
"peak_pss_mib": 102.46,
"processes": 1
},
{
"engine": "Chromium",
"cdp_ready_ms": 169.37,
"peak_pss_mib": 348.82,
"processes": 11
}
]Project के sample agent workload में, Moli ने 34.85 ms में CDP connection स्वीकार किया, जबकि Chromium के लिए 169.37 ms लगे। Peak PSS (proportional set size; shared pages को उन्हें साझा करने वाली processes के बीच बाँटकर गिनी गई memory) 102.46 MiB था, जबकि Chromium के लिए 348.82 MiB था। Structural difference अंतिम column में है: 1 process की तुलना में 11। एक process को systemd supervise कर सकता है और एक cgroup उसकी सीमा तय कर सकता है। इसी कारण अगला section छोटा है।
loopback पर moli serve को systemd service के रूप में चलाएँ
जब किसी agent को अपने लिए browser के तैयार रहने की आवश्यकता हो, तब server को service के रूप में चलाएँ। जब इसकी आवश्यकता न हो, तब प्रत्येक URL के लिए moli fetch का उपयोग करते रहें, क्योंकि idle server फिर भी memory घेरता है।
port 9222 को public interface पर bind न करें। CDP में किसी भी प्रकार का authentication चरण नहीं होता। जिस व्यक्ति को उस port तक पहुँच मिल सकती है, वह browser को नियंत्रित कर सकता है और browser की पहुँच में मौजूद कोई भी सामग्री पढ़ सकता है। इसमें आपकी profile directory में मौजूद cookies भी शामिल हैं। इसे 127.0.0.1 पर ही रखें। किसी दूसरी machine से SSH tunnel (ssh -L 9222:127.0.0.1:9222 user@your-vps) या private VPN interface के माध्यम से पहुँचें, और agent को tunnel के अपने सिरे पर http://127.0.0.1:9222 से connect करने दें।
एक service user बनाएँ, फिर unit file बनाएँ:
sudo useradd --system --home-dir /var/lib/moli --shell /usr/sbin/nologin moli/etc/systemd/system/moli.service लिखें:
[Unit]
Description=Moli headless browser CDP server
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=moli
Group=moli
ExecStart=/usr/local/bin/moli serve --host 127.0.0.1 --port 9222 --profile-dir /var/lib/moli/profile --block-private-networks
Restart=on-failure
RestartSec=2
StateDirectory=moli
MemoryAccounting=yes
MemoryMax=768M
NoNewPrivileges=yes
PrivateTmp=yes
ProtectHome=yes
ProtectSystem=strict
[Install]
WantedBy=multi-user.targetsudo systemctl daemon-reload
sudo systemctl enable --now moli.service
systemctl status moli.service
curl -s http://127.0.0.1:9222/json/versionsystemctl status को active (running) दिखाना चाहिए, और curl को discovery JSON लौटाना चाहिए। ProtectSystem=strict इस unit के लिए पूरे filesystem को read-only mount करता है। इसलिए यहाँ StateDirectory=moli वैकल्पिक नहीं है: यह /var/lib/moli बनाता है, जिसका owner service user होता है, और केवल उस path को writable बनाता है। यदि कोई unit शुरू होने के बाद journalctl -u moli में permission error के साथ बंद हो जाए, तो वह लगभग हमेशा ऐसी जगह लिखने का प्रयास कर रहा होता है जिसे ProtectSystem ने अभी read-only बनाया है। इसलिए उस path को state directory के अंतर्गत ले जाएँ।
MemoryMax=768M ही इसे आपके application के साथ सुरक्षित रूप से चलाने योग्य बनाता है। Unit को अपना अलग cgroup मिलता है। जब वह cgroup अपनी limit से अधिक हो जाता है, तो kernel उसके अंदर की किसी प्रक्रिया को समाप्त कर देता है और बाकी system को प्रभावित नहीं करता। journal में इसका रिकॉर्ड दिखाई देता है:
moli.service: A process of this unit has been killed by the OOM killer.इस line को sizing signal की तरह पढ़ें। या तो pages आपकी योजना से अधिक भारी हैं, या limit बहुत कम है। संख्या अपने pages के measurement के आधार पर निर्धारित करें। यह अगला section है। यही accounting flags machine की किसी अन्य service को भी उसकी सीमा में रखते हैं, और systemd से memory और CPU सीमित करना बाकी services पर भी इसी तरह काम करता है।
अपनी peak memory स्वयं मापें
प्रकाशित आंकड़े किसी और के hardware और किसी और के pages से लिए गए थे। Peak memory तय करती है कि आपका box काम करता रहेगा या नहीं, और peak पूरी तरह इस बात पर निर्भर करती है कि आप क्या load करते हैं। Size तय करने से पहले माप लें।
एक बार में fetching के लिए time binary का उपयोग करें। यह इसी नाम वाले shell builtin की तुलना में बहुत अधिक जानकारी देता है:
sudo apt update && sudo apt install -y time
/usr/bin/time -v moli fetch --dump markdown --wait-until networkidle https://example.com > /dev/nullOutput के अंत में resource statistics का एक block होता है, जिसमें Maximum resident set size (kbytes) शामिल है। MiB पाने के लिए इसे 1024 से divide करें। इसे example.com के बजाय उन दस pages पर चलाएँ, जिन पर आपका agent वास्तव में जाता है। Average के बजाय सबसे बड़ा result रखें, क्योंकि OOM killer peak पर प्रतिक्रिया करता है।
Service के लिए वह counter पढ़ें, जिसे kernel उसके cgroup के लिए पहले से रखता है:
cat /sys/fs/cgroup/system.slice/moli.service/memory.peak
systemd-cgtop -mmemory.peak bytes की संख्या है। यह unit के पिछली बार start होने के बाद का high-water mark है, इसलिए restart करने पर यह reset हो जाता है। यही figure वह मान है, जिससे MemoryMax ऊपर होना चाहिए। साथ ही, उस सबसे भारी page के लिए अतिरिक्त जगह रखें, जिसे आपने अभी तक visit नहीं किया है। systemd-cgtop -m प्रत्येक unit का live usage दिखाता है। आज box पर सबसे अधिक memory लेने वाली service पहचानने का यह सबसे तेज तरीका है।
Moli कहाँ विफल होता है, और आपको अभी भी Chrome की आवश्यकता कब पड़ती है?
यह project 1,308 तुलनीय browser automation tasks का benchmark भी चलाता है और कई engines के scores प्रकाशित करता है।
इस चार्ट के पीछे का डेटा
[
{
"engine": "Chrome",
"success_rate_pct": 99.85
},
{
"engine": "Moli 0.1.1",
"success_rate_pct": 81.88
},
{
"engine": "Kitesurf",
"success_rate_pct": 62.08
},
{
"engine": "Lightpanda",
"success_rate_pct": 53.29
},
{
"engine": "Obscura",
"success_rate_pct": 44.88
}
]इन 5 engines में Moli 0.1.1 ने 81.88 प्रतिशत tasks पूरे किए, जबकि reference engine Chrome ने 99.85 प्रतिशत tasks पूरे किए। यह project अपने ही suite पर स्वयं को score कर रहा है, इसलिए इसे स्वतंत्र परिणाम के बजाय एक दावे के रूप में देखें।
व्यावहारिक निष्कर्ष सरल है। Moli पर लगभग हर पांच में से एक task विफल हुआ, जिसे Chrome ने पूरा कर लिया। यदि आपका agent आपके नियंत्रण वाले pages के एक निश्चित set पर जाता है, तो यह ratio आपको बहुत कम जानकारी देता है, क्योंकि आपके pages या तो काम करते हैं या नहीं करते, और आप इसका पता आज ही लगा सकते हैं। यदि आपका agent open web browse करता है, तो यह वास्तविक failure rate है और आपको अपने design में इसके लिए व्यवस्था करनी होगी।
Project के बताए scope से यह अनुमान लगाया जा सकता है कि क्या विफल होगा।
- वे applications जो अपना interface DOM के बजाय Canvas element में draw करती हैं, क्योंकि Canvas fidelity को स्पष्ट रूप से scope से बाहर रखा गया है
- वह सब कुछ जिसे WebGL या GPU compositing की आवश्यकता है, क्योंकि GPU compositor उपलब्ध नहीं है
- DRM-protected video और demanding media playback
- वे visual tests जो Chrome के विरुद्ध pixel-exact screenshots की पुष्टि करते हैं, क्योंकि Chrome के साथ parity लक्ष्य नहीं है
Project द्वारा उद्धृत दूसरा आंकड़ा, जिसमें एक full run में 1.612 million web platform tests pass हुए, standards coverage के बारे में है। यह उन sites के बारे में कोई promise नहीं है, जिन पर आपका agent जाएगा। कोई page केवल अच्छी तरह समर्थित standards का उपयोग कर सकता है और फिर भी bot check पर विफल हो सकता है; कोई भी engine score इसे cover नहीं करता।
इसलिए design में fallback रखें। हर URL पहले Moli को भेजें। जब कोई page खाली लौटे या कोई selector कभी दिखाई न दे, तो उसी URL को Playwright से real Chrome चलाकर फिर से try करें। यह किसी बड़ी machine पर या ऐसे schedule पर करें, जहाँ 773 MiB process चलाना वहनीय हो। अधिकांश agents अपना अधिकांश समय सामान्य pages पर बिताते हैं, इसलिए छोटा engine volume संभालता है और महंगा engine कठिन मामलों को संभालता है।
FAQ
क्या Moli मेरे agent के लिए headless Chrome की जगह ले सकता है?
Pages पढ़ने, text निकालने और सामान्य clicking के लिए आम तौर पर हाँ। Project के अपने 1,308 tasks वाले benchmark में इसने 81.88 percent tasks पूरे किए, जबकि Chrome का आंकड़ा 99.85 percent था। इसलिए लगभग हर पाँच में से एक task ऐसा होता है जिसे Moli नहीं कर सकता। Canvas-rendered applications, WebGL और DRM video ज्ञात सीमाएँ हैं। उन URLs को real Chrome पर भेजें, बजाय इसके कि सब कुछ वापस उसी पर switch कर दें।
VPS पर Moli को कितनी RAM चाहिए?
Project के अनुसार 192-URL crawl में median RSS 73 MiB था। Sample agent episode में peak PSS 102.46 MiB था, जबकि headless Chrome का median 773 MiB था। ये उनके pages पर दिए गए आंकड़े हैं। One-shot use के लिए किसी moli fetch call के आसपास /usr/bin/time -v चलाकर अपने आंकड़े मापें। Service के लिए /sys/fs/cgroup/system.slice/moli.service/memory.peak पढ़ें। फिर MemoryMax को दिखने वाले सबसे बड़े आंकड़े से अधिक रखें।
क्या port 9222 को internet पर expose करना सुरक्षित है?
नहीं। CDP में authentication नहीं है। इसलिए जो भी उस port तक पहुँच सकता है, वह आपके browser को चला सकता है और browser की पहुँच वाली कोई भी चीज़ पढ़ सकता है। --host 127.0.0.1 रखें। किसी दूसरी machine से endpoint तक SSH tunnel या private VPN interface के माध्यम से पहुँचें। यदि किसी अन्य address पर bind करना आवश्यक हो, तो उसे private interface पर रखें और firewall से access नियंत्रित करें।
मेरा screenshot खाली क्यों है, या मेरा click किसी element पर क्यों नहीं जा रहा?
Layout default रूप से disabled है। README में default policy LayoutPolicy::Mock दी गई है। इसलिए element geometry वास्तविक नहीं होती और page पर किसी box पर निर्भर कोई भी कार्य काम नहीं करता। Server को moli serve --layout के साथ start करें। या moli fetch में --layout जोड़ें। इसके बाद screenshot और coordinate paths काम करने लगते हैं। Missing images के लिए अलग flag है: --resource।
मुझे Moli का कौन-सा version install करना चाहिए?
एक version pin करें और उसे record करें। August 2026 तक current release 1.0.1 है, जबकि project द्वारा प्रकाशित benchmark figures 0.1.1 पर मापे गए थे। इसलिए किसी अन्य व्यक्ति के साथ तुलना करते समय दोनों versions को interchangeable न मानें। उस tag का moli-x86_64-unknown-linux-gnu.tar.gz download करें और binary स्वयं install करें। Shell installer पर निर्भर न रहें, क्योंकि वह आपके fetch किए गए tag के बजाय newest release resolve करता है। इसके बाद moli --version से पुष्टि करें।