DEV Community

YMori
YMori

Posted on

Kaggle Code Competitions : GitHub Actions + Kaggle API Cloud Workflow

The Problem

The goal: edit a notebook anywhere, push to GitHub, and have it appear on Kaggle ready to submit.

The Workflow

Edit notebook → git push → GitHub Actions → kaggle kernels push → Submit via browser
Enter fullscreen mode Exit fullscreen mode
Step Automated? How
Edit notebook - Any device
Upload to Kaggle Yes GitHub Actions + kaggle kernels push
Submit Manual Browser: "Submit to Competition"
Check score Yes kaggle competitions submissions API

Why Can't We Fully Automate?

I spent a lot of time trying to make submission fully automatic. Here's what I found:

The Kaggle API's CreateCodeSubmission endpoint returns 403 Forbidden:

Permission 'kernelSessions.get' was denied
Enter fullscreen mode Exit fullscreen mode

I tested every combination:

Auth Method CLI Version API Result
Legacy API Key 1.8.4 competition_submit_code 403
New API Token (KGAT_...) 1.8.4 competition_submit_code 403
New API Token (KGAT_...) 2.0.0 competition_submit_code 403
New API Token (KGAT_...) 2.0.0 competitions submit (file) 400

Why?

  • Permission scope limitation: kernelSessions.get monitors notebook execution sessions. Public API tokens don't include this scope.
  • Code competitions are special: Unlike uploading a CSV, notebook submission involves re-execution and progress monitoring on the platform, requiring higher-level control permissions.
  • File submission doesn't work either: Code competitions reject direct CSV uploads (400 Bad Request).

Conclusion: Until the API is updated, the hybrid approach (automate deployment, manually submit) is the most practical.

Setup

Directory Structure

kaggle-competitions/
├── .github/workflows/
│   └── kaggle-push.yml
├── deep-past/
│   ├── kernel-metadata.json
│   └── deep-past-baseline.ipynb
Enter fullscreen mode Exit fullscreen mode

kernel-metadata.json

{
  "id": "your-username/your-kernel-slug",
  "title": "Your Kernel Title",
  "code_file": "your-notebook.ipynb",
  "language": "python",
  "kernel_type": "notebook",
  "is_private": "false",
  "enable_gpu": "false",
  "enable_internet": "false",
  "competition_sources": ["competition-slug"]
}
Enter fullscreen mode Exit fullscreen mode

Critical: enable_internet must be "false". Internet ON prevents the notebook from being eligible for submission in code competitions.

GitHub Actions Workflow

name: Kaggle Kernels Push

on:
  workflow_dispatch:
    inputs:
      notebook_dir:
        description: 'Notebook directory'
        required: true
        type: string

jobs:
  push:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.12'

      - name: Install kaggle CLI
        run: pip install kaggle

      - name: Push notebook to Kaggle
        env:
          KAGGLE_API_TOKEN: ${{ secrets.KAGGLE_API_TOKEN }}
        run: kaggle kernels push -p "${{ inputs.notebook_dir }}"
Enter fullscreen mode Exit fullscreen mode

Set KAGGLE_API_TOKEN in your repo's GitHub Secrets (Kaggle Settings → API Tokens → Generate).

Gotchas

1. Data Path

competition_sources mounts at:

/kaggle/input/competitions/<slug>/
Enter fullscreen mode Exit fullscreen mode

NOT /kaggle/input/<slug>/. The competitions/ subdirectory is easy to miss.

2. Windows Encoding

kaggle kernels output crashes on Windows with non-ASCII characters (cp932 error). Use the API directly with urllib.request and UTF-8 decoding instead.

3. Kernel Slug Must Match Title

If your kernel-metadata.json title doesn't resolve to the specified id slug, you'll get a 400 error on push. Keep them consistent.

Results

I used this workflow for the Deep Past Challenge (Akkadian → English translation):

  • Pushed a TF-IDF nearest neighbor baseline via GitHub Actions
  • Submitted via browser
  • Public Score: 5.6

The iteration cycle is fast: edit locally → push → submit → check score.

Summary

Full automation of Kaggle code competition submissions isn't possible via the public API (as of Feb 2026). But automating everything up to the submit button still saves a lot of time and lets you work from any device.

The one manual click is a small price to pay.

Top comments (2)

Collapse
 
metrosmash profile image
Ajiboye Toluwalase

This must shave off some time while parttiipating on competitions expecially if you are not using the kaggle notebooks
saved this method so i can try it if i am doing a local to kaggle during competitions

Collapse
 
yasumorishima profile image
YMori

Thanks for the kind words! Exactly — once you set it up, you can just push and let GitHub Actions handle the upload, which saves a lot of back-and-forth. Hope it works well for you when you try it in a competition. Good luck! 🚀