cd /news/ai-tools/creating-a-website-chat-widget-with-… · home topics ai-tools article
[ARTICLE · art-42446] src=discuss.huggingface.co ↗ pub= topic=ai-tools verified=true sentiment=↓ negative

Creating a Website Chat Widget with Gradio Part IV

A website owner reports that their Gradio-powered AI chatbot widget stopped working due to a CORS policy change in Gradio, which now requires the 'Access-Control-Allow-Credentials' header to be 'true'. The user seeks a solution other than rewriting code to bypass CORS.

read3 min views1 publishedJun 28, 2026

A while back @John6666 help set up an AI gradio chatbot on my website. Everything was working fine, with the AI chatbot doing a great job.

However, I’ve not been monitoring it, and sometime recently(?) it stopped working. The problem is on the client I get the error:

Access to fetch at [huggingfacespace] from origin [mywebsite] has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: The value of the ‘Access-Control-Allow-Credentials’ header in the response is ‘’ which must be ‘true’ when the request’s credentials mode is ‘include’.

After looking around this seems to be related to a change to gradio where they fixed a security issue with CORS. However, the solution I found appeared to suggest the fix was to basically re-write the code to “get around” CORS rather than using it.

It that really the only solution?

This is the code that was working before the “fix” broke it:

(website client code)

<script type="module">
    import { Client } from "https://cdn.jsdelivr.net/npm/@gradio/client@/dist/index.min.js";
    import { marked } from "https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js";
    
    async function initChatWidget() {
        const client = await Client.connect("https://[myspace].hf.space/");
        
        const conversationId = crypto.randomUUID();                         // NEW FOR LOGGING
        const chatToggle = document.getElementById('chat-toggle');
        const chatContainer = document.getElementById('chat-container');
        const closeChat = document.getElementById('close-chat');
        const chatInput = document.getElementById('chat-input');
        const sendButton = document.getElementById('send-message');
        const messagesContainer = document.getElementById('chat-messages');
    
        chatToggle.addEventListener('click', () => {
            chatContainer.classList.remove('hidden');
        });
    
        closeChat.addEventListener('click', () => {
            chatContainer.classList.add('hidden');
        });
    
        // Auto-open chat on contact page
if (window.location.pathname.includes('/contact') ||
    window.location.pathname.endsWith('/contact.html') ||
    window.location.pathname.includes('/account') ||
    window.location.pathname.endsWith('/account.html')) {
    chatContainer.classList.remove('hidden');
}
    
        function appendMessage(text, sender) {
            const div = document.createElement("div");
            div.className = `message ${sender}-message`;
            div.textContent = text;  // or marked.parse(text) if you're using marked
            messagesContainer.appendChild(div);
            messagesContainer.scrollTop = messagesContainer.scrollHeight;
        }
    
        async function sendMessage() {
            const userMessage = chatInput.value.trim();
            if (!userMessage) return;

            appendMessage(userMessage, 'user');
            chatInput.value = '';

            try {
                const result = await client.predict("/chat", {
                    message: {"text": userMessage, "files": []},
                conversation_id: conversationId,                        // NEW FOR LOGGING
                });

      const lines = result.data[0];             // list of strings from Python
      const botMessage = Array.isArray(lines) ? lines.join("\n") : String(lines);
      appendMessage(botMessage, "bot");
            
            } catch (error) {
                console.error('Error:', error);
                appendMessage('Sorry, there was an error processing your request.', 'bot');
            }
        }
 
        sendButton.addEventListener('click', sendMessage);
        chatInput.addEventListener('keypress', (e) => {
            if (e.key === 'Enter') sendMessage();
        });
    
      // PRE-SEED: show a bot greeting as soon as the widget is ready
      appendMessage("Hey there! What can I help you with today?", "bot");
      }
    
      initChatWidget();
</script>

(code on huggingface space)

import json
import requests # for API code
import holidays # details of UK holidays
from datetime import datetime, timedelta, date, time
from openai import OpenAI
import gradio as gr
import os
import uuid

say_hello = [
    {
        "role": "assistant",
        "content": "Hey there! What can I help you with today?",
    }
]

def chat(message, history, conversation_id):
    if not conversation_id:
        conversation_id = str(uuid.uuid4())

    if isinstance(message, dict): # make sure the user comment is in an acceptable format, and convert to a string
        user_text = message.get("text", "")
    else:
        user_text = str(message)
    history = [{"role":h["role"], "content":h["content"]} for h in history] # clean history for some non openai models
    messages = [{"role": "system", "content": system_message}] + history + [{"role": "user", "content": user_text}] # illusion of memory
    response = openai.chat.completions.create(model=MODEL, messages=messages, tools=tools)


    response_as_a_list = [response.choices[0].message.content] # need to change reponse from string to a list of strings for the chatbot widget
    return response_as_a_list

conversation_id_input = gr.Textbox(
    label="conversation_id",
    visible=False,
    value="",
)

chatbot = gr.Chatbot(
    value=say_hello,
    type="messages",
)

my_chat = gr.ChatInterface(
    fn=chat,
    type="messages",
    multimodal=True,
    title="Widget Demo Bot",
    api_name="chat",
    additional_inputs=[conversation_id_input],  # extra arg to fn
)

if __name__ == "__main__": 
    my_chat.launch(ssr_mode=False)
── more in #ai-tools 4 stories · sorted by recency
── more on @gradio 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/creating-a-website-c…] indexed:0 read:3min 2026-06-28 ·