JSON Response Issue with Roboflow Inference API in Deployed Web App

I’m facing an issue with my web app when using the Roboflow Inference API after deployment. Locally, the endpoint returns the expected JSON response, but once deployed, it occasionally returns an HTML response (e.g., <!DOCTYPE html>), which causes a SyntaxError: Unexpected token '<'. This happens despite the endpoint responding with a 200 OK status.

  • Project Type:Parking Management System with license plate detection (ALPR).
  • Operating System & Browser: Chrome
  • Project Universe Link or Workspace/Project ID:
  • API Endpoint Used: Roboflow Inference API
  • Problem Details:
  • The web app fetches frames from a video feed and sends them to the /detect endpoint in my Flask server.
  • The Flask server calls the Roboflow model inference API and should return the detected license plate text and vehicle type as JSON.
  • The server logs show a 200 OK response, but the client sometimes receives unexpected HTML instead of JSON.**

Additional Note: This is deploy on Render.

This is the related codes below.

Load the model

print(“Loading model…”)
model = inference.get_model(“plate-number-recognition-prqx4/2”)
print(“Model successfully loaded.”)

import easyocr
from PIL import Image
import numpy as np
from flask import request, jsonify

Initialize the easyocr reader

reader = easyocr.Reader([‘en’])

@parking.route(‘/detect’, methods=[‘POST’])
def detect():
if ‘image’ not in request.files:
print(“No image uploaded”)
return jsonify({‘error’: ‘No image uploaded’}), 400

try:
    # Get the image from the request
    file = request.files['image']
    img = Image.open(file.stream)
    img_np = np.array(img)  # Convert PIL Image to numpy array for processing

    # Run inference
    print("Running inference...")
    result = model.infer(image=img_np)
    print("Inference result:", result)

    if len(result) > 0:
        response = result[0]
        detected_text = ""
        vehicle_type_detected = None

        for prediction in response.predictions:
            x1 = prediction.x - (prediction.width / 2)
            x2 = prediction.x + (prediction.width / 2)
            y1 = prediction.y - (prediction.height / 2)
            y2 = prediction.y + (prediction.height / 2)

            # Crop the license plate from the image
            license_plate = img_np[int(y1):int(y2), int(x1):int(x2)]
            license_plate_image = Image.fromarray(license_plate)

            # Use easyocr to extract text from the cropped license plate
            extracted_text = reader.readtext(np.array(license_plate_image), detail=0, paragraph=True)

            if extracted_text:
                # Clean and validate the extracted text
                cleaned_text = extracted_text[0].strip().replace(" ", "").upper()
                validated_text, vehicle_type = validate_vehicle_plate(cleaned_text, vehicle_type='both')

                if validated_text != "Invalid plate format":
                    detected_text += validated_text + " "
                    vehicle_type_detected = vehicle_type  # Set the detected vehicle type

        print("Detected text:", detected_text.strip())
        print("Vehicle type detected:", vehicle_type_detected)

        return jsonify({
            'text': detected_text.strip(),
            'vehicle_type': vehicle_type_detected
        })
    else:
        print("No plates detected")
        return jsonify({'text': 'No plates detected', 'vehicle_type': 'Unknown'}), 200
except Exception as e:
    print("Error during inference or processing:", e)
    return jsonify({'error': 'Inference error'}), 500

javascript

function processVideo() {
const canvas = document.createElement(‘canvas’);
const context = canvas.getContext(‘2d’);

            setInterval(() => {
                canvas.width = video.videoWidth;
                canvas.height = video.videoHeight;
        
                context.drawImage(video, 0, 0, canvas.width, canvas.height);
        
                canvas.toBlob((blob) => {
                    const formData = new FormData();
                    formData.append('image', blob, 'frame.jpg');
        
                    fetch('/parking/detect', {
                        method: 'POST',
                        body: formData
                    })
                    .then(response => {
                        // Log the content type to verify JSON
                        console.log('Response content type:', response.headers.get('Content-Type'));
                        
                        return response.json(); // Attempt to parse as JSON
                    })
                    .then(data => {
                        console.log('Received data:', data); // Log the response
        
                        if (data.text) {
                            detectedText.value = data.text;  // Display detected plate number
                        }
                        if (data.vehicle_type) {
                            detectedVehicleType.value = data.vehicle_type;  // Display vehicle type
                        }
                    })
                    .catch(error => console.error("Error processing the frame or invalid JSON response: ", error));
                }, 'image/jpeg');
            }, 2000);  // Process every 2 seconds
        }



When an endpoint that only serves JSON returns HTML, it is likely returning the HTTP 502 Bad Gateway error page. In these situations it is necessary for the app’s owner to review logs and perform debugging to understand why it is returning an error, preventing the expected JSON from being returned, and preventing the retrieval, and parsing of said JSON.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.