How Do I Fix a SSL Connection Error with Axios in React JS

Recently, while working on a React JS project that communicates with a Python backend via REST APIs, I ran into a frustrating issue. Every time I tried to send a POST request using Axios to upload files, the browser threw a net::ERR_SSL_PROTOCOL_ERROR, and nothing seemed to work after that.

If you’ve seen this error and you’re wondering whether it’s your frontend, your API, or your network setup I’ve been there. Here’s a full breakdown of how I encountered the issue, what I learned, and how I fixed it.

Original Code

This is the original Axios setup I had in my React component for POST and GET requests:

let postR = [];

results.map(async result => {
postR.push(
axios.post(
'https://52.14.247.16:5000/process',
{ result },
{ headers: { 'Content-Type': 'application/json' } }
)
);
});

Promise.all(postR).then(res => {
console.log(res);
this.getRequest();
});

getRequest = async () => {
axios
.get(
'https://52.14.247.16:5000/start/' +
this.props.maxLen +
'+' +
this.props.minLen +
'+' +
this.props.maxDistance +
'+' +
this.props.minDistance +
'+' +
this.props.MicrobeType +
'+' +
this.state.files.length
)
.then(response => {
console.log(response.data);
this.downloadTxtFile(response.data.value);
})
.catch(function (error) {
console.log(error);
alert('Problem at the server\nTry later\n' + error);
});
};

I expected this setup to simply post some file-related data and then trigger a response process. Instead, I was greeted by this nasty error.

SSL Protocol Error in Axios

net::ERR_SSL_PROTOCOL_ERROR
Uncaught (in promise) Error: Network Error

After digging into it, I realized this wasn’t an Axios-specific bug. Instead, it was an SSL issue coming from the backend server.

Explanation of the Error

Here’s what I learned the hard way:

  • Self-signed certificates often break SSL unless the client (browser) explicitly trusts them.
  • Expired or misconfigured certificates also cause SSL to fail.
  • Using raw IP addresses with SSL is a common cause of this error because SSL certificates are bound to domain names, not IPs.
  • Flask HTTPS misconfigurations can silently break SSL.

So even though the frontend code was trying its best to connect securely, the server was not properly set up for SSL over HTTPS.

Solution Suggestion

Use a Domain Instead of an IP

Browsers are strict with SSL certificates. If your cert was issued for example.com, but you access it via https://52.14.247.16, you will always get SSL errors.

Fix: Get a domain name, and set up your backend to respond under that domain using a valid SSL certificate (e.g. from Let’s Encrypt).

Test Without HTTPS in Development

In development, it’s okay to use HTTP temporarily:

axios.post('http://localhost:5000/process', data);

Note: Never use HTTP in production unless you’re behind a proxy that handles SSL.

Fix SSL on Flask Backend

Here’s how I added HTTPS support to my Flask app:

from flask import Flask
app = Flask(__name__)

if __name__ == '__main__':
app.run(ssl_context=('cert.pem', 'key.pem'))

Make sure:

  • cert.pem and key.pem are valid and not expired.
  • You use a domain name that matches the cert.

Upload Files Using Axios

Once I fixed the SSL issue, I also improved the way I was uploading files. Previously, I was sending JSON like { result }, which is incorrect for file uploads.

Here’s how I refactored the code to properly send files using FormData:

let postRequests = [];

this.state.files.forEach(file => {
const formData = new FormData();
formData.append('file', file);

postRequests.push(
axios.post('https://yourdomain.com:5000/process', formData, {
headers: { 'Content-Type': 'multipart/form-data' }
})
);
});

Promise.all(postRequests)
.then(responses => {
console.log(responses);
this.getRequest(); // Continue after upload success
})
.catch(error => {
console.error("File upload error:", error);
alert("Upload failed. Check server or SSL config.");
});

Update Flask API to Receive File

To match the new frontend logic, I also updated my Python backend:

from flask import Flask, request

app = Flask(__name__)

@app.route('/process', methods=['POST'])
def process_file():
if 'file' not in request.files:
return {'error': 'No file part'}, 400

file = request.files['file']
filename = file.filename

# Process file contents here
content = file.read()
return {'message': f'{filename} processed'}, 200

Extra Feature I Practice

After getting the basic logic working, I challenged myself with extra features:

Track Upload Progress

onUploadProgress: progressEvent => {
let percent = Math.round((progressEvent.loaded * 100) / progressEvent.total);
console.log(`Upload progress: ${percent}%`);
}

Final Thought

The dreaded net::ERR_SSL_PROTOCOL_ERROR turned out to be a server-side SSL issue, not a bug with Axios itself. The problem stemmed from attempting to send HTTPS requests to a raw IP address using a self-signed or invalid certificate something modern browsers are designed to reject for security reasons. To avoid these issues, it’s essential to use a proper domain name with a valid SSL certificate and ensure your Flask server is correctly configured for HTTPS.

Additionally, when dealing with file uploads, using FormData is the correct approach sending file data as JSON simply won’t work. While it’s technically possible to bypass SSL checks in development by setting process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0', this should never be done in production; it’s the equivalent of taping over a warning light in your car. Once I addressed the SSL configuration and adjusted my file upload strategy, everything started working smoothly my files uploaded without errors, and my React app became stable and reliable, letting me focus on building actual features instead of troubleshooting cryptic network failures.

Related blog posts