I'm trying to send some data from a Chrome extension content script to a background script to my local python file. It goes from the content script to the background script fine, but when I try to send it to the python file, I just get "POST http://localhost:5000/bootstrap 400 (BAD REQUEST)." Can't figure out what's going on. I'm new to this. Many thanks!
background.js
// Sending messages from background / event page
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
    if (changeInfo.status == 'complete') {
        chrome.tabs.query({ active: true }, function(tabs) {
            const msg = "Hello from background ";
            chrome.tabs.sendMessage(tabs[0].id, { "message": msg });
        })
    }
});
// Listening to messages page
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    console.log(request);
    var articleData = request
    // Callback for that request
$.ajax({
    type: 'POST',
    url: 'http://localhost:5000/bootstrap',
    data: articleData,
    success: function (newArticle){
       alert('success');
    }
    })
    sendResponse({ message: "Background has received that message " });
});
relevant part of fakenews.py
@app.route('/bootstrap', methods=['GET', 'POST'])
def bootstrap():
    posted = 1
    print ("bootstrap")
    global article
    if request.method == 'POST':
        if not request.form['title'] or not request.form['url'] or not request.form['image_url'] or not request.form['snippet']:
            flash('Please enter all the fields', 'error')
        else:
            article = Article(request.form['title'], request.form['url'], request.form['image_url'],
                               request.form['snippet'])
            db.session.add(article)
            try:
                db.session.commit()
            except exc.SQLAlchemyError:
               flash('Article url already exists, failed to post new article')
               posted = 0
               #return render_template('/error.html', article_url=article.url)
            article_list = Article.query.filter_by(url=article.url)
            if posted == 1:
                flash('Record was successfully added')
            else:
                db.session.rollback()
                article_list = Article.query.filter_by(url=article.url)
                article=article_list[0]
            print ("article.id=" + str(article.id))
            vote_choices = VoteChoice.getVoteChoiceList()
            return render_template('/votefor.html', article_id=article.id,
                                   article_title=article.title,
                                   article_url=article.url, vote_choices=vote_choices
                                   )
relevant part of content.js
chrome.runtime.sendMessage({ message: [title, image, url] }, function(response) {
    console.log(response);
});
// Listening to messages in Context Script
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    console.log(request);
    // Callback
    sendResponse({ message: 'Content script has received that message ⚡' })
})
});
manifest.json
  {
    "manifest_version": 2,
    "name": "OrangeBox",
    "version": "1.0",
    "permissions": ["http://localhost/" ,"tabs"],
    "content_scripts": [
        {
            "matches": ["<all_urls>"],
            "js": ["contentScript.js"]
        }
    ],
    "background": { "scripts": ["jquery-3.4.1.js", "background.js"],  "persistent": false },
    "content_scripts": [
  {
    "matches": [
      "<all_urls>"
    ],
    "js": ["jquery-3.4.1.js", "waitForKeyElements.js", "content.js"]
  }
]
}