crawl4ai version
v0.9.3
Expected Behavior
The Playground (/playground/) should work for all endpoint modes. The Advanced Config editor is a /crawl-only feature (the panel is hidden for md/llm), so selecting the md endpoint and clicking Run should simply POST { url, f, q, c } to /md — the server builds its own CrawlerRunConfig internally (handle_markdown_request). No client-side config validation should be involved.
Current Behavior
runCrawl() in deploy/docker/static/playground/index.html calls pyConfigToJson() unconditionally for every endpoint, including md and llm. pyConfigToJson() reads the Advanced Config CodeMirror editor (which defaults to the Python snippet CrawlerRunConfig(stream=True, cache_mode=CacheMode.BYPASS,)) and POSTs it to /config/dump using the removed legacy code protocol:
{ "type": "CrawlerRunConfig", "code": "CrawlerRunConfig(\n stream=True,\n cache_mode=CacheMode.BYPASS,\n)" }
Since the security hardening (eval removal from /config/dump + untrusted trust boundary), the server parses request bodies with Provenance.UNTRUSTED and code is a globally forbidden field, so the request is rejected with:
{ "detail": "field 'code' is not permitted on CrawlerRunConfig from an untrusted request" }
In runCrawl() the 400 error triggers the catch branch. The fallback (minimal { crawler_config: { type: 'CrawlerRunConfig', params: { stream: true } } }) only applies when endpoint === 'crawl' and the editor text contains stream=True. For md/llm the code path aborts the whole run, so the md mode is unusable even without touching the Advanced Config. The only workaround today is pasting empty text / relying on nothing, but since the editor has a non-empty default template, pyConfigToJson() always runs.
Is this reproducible?
Yes
Inputs Causing the Bug
- URL(s): https://example.com
- Endpoint: md (and llm)
- Advanced Config: default
Steps to Reproduce
1. Start the Docker server and open http://localhost:11235/playground/
2. Leave the endpoint set to "md" (default), enter any URL, leave Advanced Config untouched
3. Click "Run"
4. Observe: status flips to "error", response shows
`{ "error": "field 'code' is not permitted on CrawlerRunConfig from an untrusted request" }`
and the /md request is never sent
Code snippets
OS
Docker
Python version
3.12.14
Browser
Chrome
Browser version
No response
Error logs & Screenshots (if applicable)

crawl4ai version
v0.9.3
Expected Behavior
The Playground (/playground/) should work for all endpoint modes. The Advanced Config editor is a /crawl-only feature (the panel is hidden for md/llm), so selecting the md endpoint and clicking Run should simply POST { url, f, q, c } to /md — the server builds its own CrawlerRunConfig internally (handle_markdown_request). No client-side config validation should be involved.
Current Behavior
runCrawl() in deploy/docker/static/playground/index.html calls pyConfigToJson() unconditionally for every endpoint, including md and llm. pyConfigToJson() reads the Advanced Config CodeMirror editor (which defaults to the Python snippet CrawlerRunConfig(stream=True, cache_mode=CacheMode.BYPASS,)) and POSTs it to /config/dump using the removed legacy
codeprotocol:{ "type": "CrawlerRunConfig", "code": "CrawlerRunConfig(\n stream=True,\n cache_mode=CacheMode.BYPASS,\n)" }Since the security hardening (eval removal from /config/dump + untrusted trust boundary), the server parses request bodies with Provenance.UNTRUSTED and code is a globally forbidden field, so the request is rejected with:
{ "detail": "field 'code' is not permitted on CrawlerRunConfig from an untrusted request" }In runCrawl() the 400 error triggers the catch branch. The fallback (minimal { crawler_config: { type: 'CrawlerRunConfig', params: { stream: true } } }) only applies when endpoint === 'crawl' and the editor text contains stream=True. For md/llm the code path aborts the whole run, so the md mode is unusable even without touching the Advanced Config. The only workaround today is pasting empty text / relying on nothing, but since the editor has a non-empty default template, pyConfigToJson() always runs.
Is this reproducible?
Yes
Inputs Causing the Bug
Steps to Reproduce
Code snippets
OS
Docker
Python version
3.12.14
Browser
Chrome
Browser version
No response
Error logs & Screenshots (if applicable)