Including hugging face search on a codepen page

how can i include a hugging face chatbot on a web page, so that i can access the PROMPT text area with other code?

you see, i am trying to make a robot to chat with my elderly mom. i want it to search the room for her face. On codepen i have seen ways to identify faces, and do text to speech/speech recognition… so i figured i would just IFRAME a hugging face bot and use hugging face as the chat portion, if that makes any sense??? lol

3 Likes

Using iframe with HF is always tricky…


Your setup is “static page (CodePen) + embedded Hugging Face Space (usually Gradio) + you want to programmatically control the embedded prompt (set text, submit, read outputs).” The failures come from browser security boundaries and from how Gradio embedding works.

Below are the main causes, then the clean solutions and the practical workarounds.


Background you need for this to make sense

Origins and why embeds are “walled off”

A web page has an origin = scheme + host + port (for example https://codepen.io vs https://something.hf.space). The same-origin policy prevents one origin from directly reading or changing another origin’s DOM. This is why “find the textarea inside the embedded chatbot and set its value” fails. (MDN Web Docs)

The only standard cross-origin bridge is postMessage

Browsers allow cross-origin messaging using window.postMessage(). It does not grant DOM access. It only sends data. It works only if the embedded app has code listening for messages and doing something with them. (MDN Web Docs)

Hugging Face Spaces embedding has two modes

For Gradio Spaces, Hugging Face documents:

  • <iframe> embed (simple, heavy, but predictable)
  • Web Component embed using <gradio-app> (faster, auto-resize), but you must load a Gradio JS bundle that matches the Space’s Gradio version. (Hugging Face)

Causes in your scenario

1) You cannot control the embedded prompt by DOM scripting

What you try: iframe.contentWindow.document.querySelector(...).
What happens: blocked or “very limited access” because the iframe is cross-origin. (MDN Web Docs)

Consequence: No reliable way to set the Space’s textbox value, press its send button, or read its chat output by DOM access.

2) “Parent ↔ embedded Gradio communication” is not built-in

People try parent→iframe postMessage, then ask “how do I receive it inside Gradio?” The answer is: not automatically. You need to add receiver code inside the Gradio app. (GitHub)

3) Web Component embeds can fail even when iframe works

Typical symptom: <gradio-app> loads but interaction throws “connection errored out.” This has been repeatedly reported. (Hugging Face Forums)

A common underlying cause is version mismatch: the embed docs explicitly say you must import the Gradio JS library corresponding to the Space’s Gradio version. (Hugging Face)

4) Navigation and link behavior can be intentionally restricted

If the embedded app tries to navigate the top page, sandboxing rules can block it unless specific flags are set. MDN documents these sandbox/top-navigation constraints. (MDN Web Docs)
Hugging Face staff have also stated that some embed navigation restrictions are intentional and recommend opening links in a new tab. (Hugging Face Forums)

5) Private Spaces do not embed like public pages

If the Space is private, embedding can trigger CORS/auth failures. A common rule of thumb reported by HF is: embedding the Space web page requires it to be public. (Hugging Face Forums)

6) CORS and “works on HF, fails on my site”

Even with public Spaces, you can hit CORS failures on embeds or API calls when hosting context changes. This has shown up in production embeds (“No ‘Access-Control-Allow-Origin’ header…”). (Hugging Face Forums)
Similarly, calling a Space API from localhost is a frequent CORS pitfall. (Hugging Face Forums)

7) Custom JS inside Gradio can be brittle across versions

Gradio supports adding custom JS, but regressions happen and some versions have had issues around custom JS behavior. (Gradio)


Solutions and workarounds that actually work

Solution A (recommended): Do not embed the chatbot UI. Call the Space as an API.

If your requirement is “other code controls the prompt,” the clean approach is:

  • Build your own textbox/chat UI in CodePen.
  • Call the Space programmatically using the Gradio JS client.

Why this works:

  • No iframe DOM access needed.
  • Your face detection, speech-to-text, buttons, and timers can update your textbox freely.
  • You send the resulting text to the Space endpoint and render the reply.

Gradio documents exactly this pattern:

  • Connect to a Space with Client.connect()
  • Inspect endpoints with view_api()
  • Call an endpoint with predict() (Gradio)

Minimal CodePen-style sketch (pattern, not copy-paste complete)

<script type="module">
  import { Client } from "https://cdn.jsdelivr.net/npm/@gradio/client/dist/index.min.js";

  const app = await Client.connect("OWNER/SPACE"); // or full hf.space URL in some cases
  const api = await app.view_api(); // inspect endpoints and payload shapes
  console.log(api);

  // Then call the correct endpoint name and payload described by view_api / “Use via API”
  const result = await app.predict("/predict", ["your text here"]);
  console.log(result.data);
</script>

Pitfall: the endpoint name is not always /predict. Use view_api() or the Space’s “Use via API” page to get the correct one. (Gradio)

When to pick this: almost always, if you are building an interactive “robot loop” (speech + face events + chat), because your control logic lives on your page, not inside the embedded app.


Workaround B: Keep embedding, but treat it as a black box UI

If you only need to display the Space UI and do not need to control its prompt:

Choose iframe when reliability matters

Iframe is simplest and tends to be more forgiving than web components when the embed environment is hostile.

If you use <gradio-app>, match versions exactly

The official embed docs: you must import a Gradio JS library matching the Space’s Gradio version, then add <gradio-app src="...">. (Hugging Face)

Expect occasional “connection errored out”

If your web component embed errors during interaction, this is a known class of issue. Trying iframe instead is a pragmatic fallback. (Hugging Face Forums)


Workaround C: If you control the Space code, add a postMessage bridge

This is the only way to “control the prompt inside the embedded UI” without switching to API calls.

How it works:

  1. Parent page sends messages with postMessage.
  2. The Space runs custom JS that listens for message events.
  3. The Space updates its internal state when it receives a valid message.

You need:

  • window.postMessage() on the parent side (MDN Web Docs)
  • Custom JS support inside Gradio to register the listener (Gradio)

Security requirements (do not skip)

If you add a message listener, treat messages as untrusted:

  • Check event.origin against an allowlist
  • Validate message structure
    OWASP explicitly recommends origin allowlisting. (OWASP Cheat Sheet Series)
    PortSwigger documents how web-message misuse becomes a vulnerability class. (PortSwigger)

Practical warning

Even with this bridge, manipulating Gradio UI via DOM selectors is fragile. Prefer “message → Python-side state → Gradio component update” rather than “message → querySelector textbox.” Gradio’s customization surface exists, but version drift is real. (Gradio)


Workaround D: Private Space constraints

If you need a Space UI embedded on a public page:

  • In many reported cases, the Space must be public to embed the web page. (Hugging Face Forums)

If your goal is “hide source code but still serve a public UI,” one workaround described by HF is:

  • Keep a private Space, then create a public Space that loads it using gr.Interface.load(). (Hugging Face Forums)
    (Validate this for your current Gradio version. Loading and auth behaviors can change.)

Workaround E: “CORS when calling APIs from the browser”

If you call Space endpoints directly from browser JS and hit CORS:

  • This is a known failure mode in embeds and in front-ends calling Spaces. (Hugging Face Forums)
    Common mitigations:
  • Prefer the official client (@gradio/client) first. It is designed for this use case. (Gradio)
  • If you still hit CORS, add a tiny proxy on your own domain (serverless function) and call that instead.
  • Avoid developing against localhost origins if the target restricts them. (Hugging Face Forums)

What I would do in your case (pragmatic)

  1. Use Solution A: own the chat UI in CodePen, call the Space via @gradio/client. (Gradio)
  2. Only embed the Space UI if you want it visually, and accept it as non-controllable.
  3. Only implement a postMessage bridge if you fully control the Space and are willing to maintain it across Gradio upgrades. Use OWASP-style origin checks. (OWASP Cheat Sheet Series)

This gives you full programmatic control for face detection and speech, which is the real requirement.


Reference set (clickable via citations)


Summary

  • Cause: cross-origin iframes block DOM control. (MDN Web Docs)
  • Best fix: build your own UI and call the Space via @gradio/client using view_api + predict. (Gradio)
  • Embed pitfalls: web components can “connection error,” version mismatch matters, navigation can be sandboxed. (Hugging Face Forums)
  • Private Spaces: embedding typically requires public visibility, or a wrapper strategy. (Hugging Face Forums)
  • If you bridge with postMessage: validate origins and message shape. (MDN Web Docs)