react-papaparse

The powerful, in-browser React CSV parser for big boys and girls

  Install  Demo  Documentation
// Parse CSV string
readString(csvString, {
  worker: true,
  complete: (results) => {
    console.log(results)
  }
})

// Convert back to CSV
const csv = jsonToCSV(jsonData)

// Parse local CSV file
<CSVReader 
  onDrop={this.handleOnDrop}
  onError={this.handleOnError}
  noDrag
  addRemoveButton
  onRemoveFile={this.handleOnRemoveFile}
>
  <span>Click to upload.</span>
</CSVReader>

// Allow download CSV file from js object
<CSVDownloader
  data={[
    {
      "Column 1": "1-1",
    },
  ]}
  filename={'filename'}
>
  Download
</CSVDownloader>

// Stream big file in worker thread
readRemoteFile(bigFileURL, {
  worker: true,
  step: (results) => {
    console.log('Row:', results.data)
  }
})
Version
3

Features

Now the fastest React CSV parser for the browser

The world's first multi-threaded CSV parser for the browser

react-papaparse can handle files gigabytes in size without crashing

Use react-papaparse when performance, privacy, and correctness matter to you

react-papaparse alleviates privacy concerns related to uploading files

Malformed CSV is handled gracefully with a detailed error report

  • Stream local and remote files
  • Multi-threaded
  • Header row support
  • Type conversion
  • Skip commented lines
  • Fast mode and easy to use
  • Graceful error handling
  • CSVDownloader


  • Frameworks

    react-papaparse strongly support Next.js, Create React App and other React frameworks. react-papaparse is the fastest React CSV parser for the browser (only works in the browser), so you need to set the component with no SSR (server-side render) in case you use readRemoteFile function.

    People react-papaparse

    react-papaparse react-papaparse

    CSV Parsing

    "Isn't parsing CSV just String.split(',')?"

    react-papaparse does it right. Just pass in the CSV string with an optional configuration.

    import { readString } from 'react-papaparse'
    
    const config = {
      worker: true,
      complete: (results) => {
        console.log(results)
      }
    }
    
    readString(csvString, config)
    
    /*
    results = {
      data: [ ... ],    // parsed data
      errors: [ ... ],  // errors encountered
      meta: { ... }     // extra parse info
    }
    */

    Delimiter Detection

    "But I don't know the delimiter..."

    That's okay. react-papaparse will scan the first few rows to find the right delimiter.

    import { readString } from 'react-papaparse'
    
    readString(csvString, {
      worker: true,
      complete: (results) => {
        console.log(results.meta.delimiter)
      }
    })
    
    // "\t"

    Local Files

    "Great, but I have a file to parse."

    Then use CSVReader component instead of readString method. Since file parsing is asynchronous, don't forget callback methods.

    Basic Upload
    Basic Upload
    import React, { Component } from 'react'
    
    import { CSVReader } from 'react-papaparse'
    
    const buttonRef = React.createRef()
    
    export default class CSVReader extends Component {
      handleOpenDialog = (e) => {
        // Note that the ref is set async, so it might be null at some point 
        if (buttonRef.current) {
          buttonRef.current.open(e)
        }
      }
      
      handleOnFileLoad = (data) => {
        console.log('---------------------------')
        console.log(data)
        console.log('---------------------------')
      }
    
      handleOnError = (err, file, inputElem, reason) => {
        console.log(err)
      }
    
      handleOnRemoveFile = (data) => {
        console.log('---------------------------')
        console.log(data)
        console.log('---------------------------')
      }
    
      handleRemoveFile = (e) => {
        // Note that the ref is set async, so it might be null at some point
        if (buttonRef.current) {
          buttonRef.current.removeFile(e)
        }
      }
    
      render() {
        return (
          <CSVReader
            ref={buttonRef}
            onFileLoad={this.handleOnFileLoad}
            onError={this.handleOnError}
            noClick
            noDrag
            onRemoveFile={this.handleOnRemoveFile}
          >
            {({ file }) => (
              <aside
                style={{
                  display: 'flex',
                  flexDirection: 'row',
                  marginBottom: 10
                }}
              >
                <button
                  type='button'
                  onClick={this.handleOpenDialog}
                  style={{
                    borderRadius: 0,
                    marginLeft: 0,
                    marginRight: 0,
                    width: '40%',
                    paddingLeft: 0,
                    paddingRight: 0
                  }}
                >
                  Browe file
                </button>
                <div
                  style={{
                    borderWidth: 1,
                    borderStyle: 'solid',
                    borderColor: '#ccc',
                    height: 45,
                    lineHeight: 2.5,
                    marginTop: 5,
                    marginBottom: 5,
                    paddingLeft: 13,
                    paddingTop: 3,
                    width: '60%'
                  }}
                >
                  {file && file.name}
                </div>
                <button
                  style={{
                    borderRadius: 0,
                    marginLeft: 0,
                    marginRight: 0,
                    paddingLeft: 20,
                    paddingRight: 20
                  }}
                  onClick={this.handleRemoveFile}
                >
                  Remove
                </button>
              </aside>
            )}
          </CSVReader>
        )
      }
    }
    Click and Drag Upload
    Click and Drag Upload
    import React, { Component } from 'react'
    
    import { CSVReader } from 'react-papaparse'
    
    export default class CSVReader extends Component {
      handleOnDrop = (data) => {
        console.log('---------------------------')
        console.log(data)
        console.log('---------------------------')
      }
    
      handleOnError = (err, file, inputElem, reason) => {
        console.log(err)
      }
    
      handleOnRemoveFile = (data) => {
        console.log('---------------------------')
        console.log(data)
        console.log('---------------------------')
      }
    
      render() {
        return (
          <CSVReader
            onDrop={this.handleOnDrop}
            onError={this.handleOnError}
            addRemoveButton
            onRemoveFile={this.handleOnRemoveFile}
          >
            <span>Drop CSV file here or click to upload.</span>
          </CSVReader>
        )
      }
    }
    
    Drag ( No Click ) Upload
    Drag ( No Click ) Upload
    import React, { Component } from 'react'
    
    import { CSVReader } from 'react-papaparse'
    
    export default class CSVReader extends Component {
      handleOnDrop = (data) => {
        console.log('---------------------------')
        console.log(data)
        console.log('---------------------------')
      }
    
      handleOnError = (err, file, inputElem, reason) => {
        console.log(err)
      }
    
      handleOnRemoveFile = (data) => {
        console.log('---------------------------')
        console.log(data)
        console.log('---------------------------')
      }
    
      render() {
        return (
          <CSVReader
            onDrop={this.handleOnDrop}
            onError={this.handleOnError}
            noClick
            addRemoveButton
            onRemoveFile={this.handleOnRemoveFile}
          >
            <span>Drop CSV file here to upload.</span>
          </CSVReader>
        )
      }
    }
    Click ( No Drag ) Upload
    Click ( No Drag ) Upload
    import React, { Component } from 'react'
    
    import { CSVReader } from 'react-papaparse'
    
    export default class CSVReader extends Component {
      handleOnDrop = (data) => {
        console.log('---------------------------')
        console.log(data)
        console.log('---------------------------')
      }
    
      handleOnError = (err, file, inputElem, reason) => {
        console.log(err)
      }
    
      handleOnRemoveFile = (data) => {
        console.log('---------------------------')
        console.log(data)
        console.log('---------------------------')
      }
    
      render() {
        return (
          <CSVReader
            onDrop={this.handleOnDrop}
            onError={this.handleOnError}
            noDrag
            addRemoveButton
            onRemoveFile={this.handleOnRemoveFile}
          >
            <span>Click to upload.</span>
          </CSVReader>
        )
      }
    }

    Remote Files

    "No — I mean, the file isn't on my computer."

    Oh, well then just pass in the URL and — of course — a callback.

    readRemoteFile('http://example.com/file.csv', {
      download: true,
      complete: (results) => {
        console.log(results)
      }
    })

    Streaming

    "Did I mention the file is huge?"

    That's what streaming is for. Specify a step callback to receive the results row-by-row. This way, you won't load the whole file into memory and crash the browser.

    readRemoteFile('http://example.com/big.csv', {
      step: (row) => {
        console.log('Row:', row.data)
      },
      complete: () => {
        console.log('All done!')
      }
    })

    Multi-Threading

    'Lovely. Now my web page locked up.'

    That happens when a long-running script is executing in the same thread as the page. Use a Worker thread by specifying worker: true. It may take slightly longer, but your page will stay reactive.

    readRemoteFile(bigFileURL, {
      worker: true,
      step: (row) => {
        console.log('Row:', row.data)
      },
      complete: () => {
        console.log('All done!')
      }
    })

    Type Conversion

    "Hey, these numbers are parsed as strings."

    Everything is parsed as strings. If you want numbers and booleans, you can enable dynamic typing to do the conversion for you.

    // Converts numeric/boolean data
    readString(csvString, {
      worker: true,
      complete: (results) => {
        console.log(results)
      },
      dynamicTyping: true
    })

    Comments

    "I forgot to mention: my CSV files have comments in them."

    Okay, first off: that's really weird. But fortunately, you can skip those lines... just specify the comment string.

    // Mostly found in academia, some CSV files
    // may have commented lines in them
    readString(csvString, {
      worker: true,
      complete: (results) => {
        console.log(results)
      },
      comments: '#'
    })

    Error Handling

    "Aw, shoot. Errors."

    react-papaparse handles errors pretty well. The CSV standard is somewhat loose ambiguous, so react-papaparse is designed for edge cases. For example, mismatched fields won't break parsing.

    // Example error:
    {
      type: 'FieldMismatch',
      code: 'TooManyFields',
      message: 'Expected 3 fields, but parsed 4',
      row: 1
    }

    JSON to CSV

    "Last thing: what about converting JSON to CSV?"

    Use jsonToCSV() function, passing in your array of arrays or array of objects. react-papaparse will figure it out.

    // Output is a properly-formatted CSV string.
    const csv = jsonToCSV(jsonData)
    

    CSVDownloader

    "Allow to download CSV file from js object."

    Just pass in the js object with an optional configuration ( setting delimiter / separator ).

    <CSVDownloader
      data={[
        {
          "Column 1": "1-1",
          "Column 2": "1-2",
          "Column 3": "1-3",
          "Column 4": "1-4",
        },
      ]}
      filename={'filename'}
      config={{}}
    >
      Download
    </CSVDownloader>
    

    data= can be a function that returns a data object.

    <CSVDownloader
      filename={'filename'}
      data={() => {
        return [
          {
            "Column 1": "1-1",
            "Column 2": "1-2",
            "Column 3": "1-3",
            "Column 4": "1-4",
          }
        ]}
      }
    >
      Download
    </CSVDownloader>
    

    Install

    npm
    $ npm install react-papaparse --save

    yarn
    $ yarn add react-papaparse